From e118f631ab29c422c1bdedde2eb177029a6bf097 Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Tue, 22 Feb 2022 11:29:24 +0100 Subject: [PATCH] Make order of children configurable. - let user activate children ordering --- dumpAst/src/main/jastadd/DumpAst.relast | 6 +- .../src/main/jastadd/GenerationBackend.jadd | 55 +++++++++++-------- .../src/main/jastadd/GenerationFrontend.jadd | 5 ++ .../src/main/jastadd/GenerationMustache.jrag | 25 +++++++++ dumpAst/src/main/jastadd/Navigation.jrag | 11 ++++ dumpAst/src/main/resources/dumpAst.mustache | 7 +++ .../st/jastadd/testDumper/TestDumperMain.java | 22 ++++++-- .../inf/st/jastadd/testDumper/TestSimple.java | 18 ++++++ 8 files changed, 116 insertions(+), 33 deletions(-) create mode 100644 dumpAst/src/main/jastadd/GenerationMustache.jrag diff --git a/dumpAst/src/main/jastadd/DumpAst.relast b/dumpAst/src/main/jastadd/DumpAst.relast index 6e640de..c6157b0 100644 --- a/dumpAst/src/main/jastadd/DumpAst.relast +++ b/dumpAst/src/main/jastadd/DumpAst.relast @@ -6,16 +6,16 @@ TypePatternCollectionMapping ::= <TypeRegex> PatternCollection ; PatternCollection ::= <TokenPattern> <ChildPattern> <RelationPattern> <AttributePattern> <NonterminalAttributePattern> ; StyleInformation ::= <NameMethod:StyleMethod> <BackgroundColorMethod:StyleMethod> <TextColorMethod:StyleMethod>; -PrintConfig ::= <Scale:double> <Version> Header* ; +PrintConfig ::= <Scale:double> <Version> <OrderChildren:boolean> Header* ; Header ::= <Value> ; DumpNode ::= <Name> <Label> <BackgroundColor> <TextColor> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ; InnerDumpNode ; -rel InnerDumpNode.DumpNode -> DumpNode ; +rel InnerDumpNode.DumpNode <-> DumpNode.ContainerOfInner ; abstract DumpChildNode ::= <Name> <Computed:boolean> ; DumpNormalChildNode : DumpChildNode ; -rel DumpNormalChildNode.DumpNode -> DumpNode ; +rel DumpNormalChildNode.DumpNode <-> DumpNode.ContainerOfNormalChild ; DumpListChildNode : DumpChildNode ::= InnerDumpNode* ; abstract DumpToken ::= <Name> <Computed:boolean> ; diff --git a/dumpAst/src/main/jastadd/GenerationBackend.jadd b/dumpAst/src/main/jastadd/GenerationBackend.jadd index d9ba8d9..682f528 100644 --- a/dumpAst/src/main/jastadd/GenerationBackend.jadd +++ b/dumpAst/src/main/jastadd/GenerationBackend.jadd @@ -453,6 +453,7 @@ aspect GenerationBackend { return result; } + // --- labelAndTextColor --- syn String DumpNode.labelAndTextColor() { if (getTextColor().isEmpty()) { return getLabel(); @@ -461,35 +462,41 @@ aspect GenerationBackend { } } + + // --- myChildren --- + syn java.util.List<DumpNode> DumpNode.myChildren() { + java.util.List<DumpNode> result = new java.util.ArrayList<>(); + for (DumpChildNode childNode : getDumpChildNodeList()) { + for (DumpNode inner : childNode.innerNodes(true)) { + result.add(inner); + } + } + return result; + } + + // --- successor --- + syn DumpNode DumpNode.successor() { + if (container() == null) { + // not contained + return null; + } + java.util.List<DumpNode> siblingsAndMe = container().myChildren(); + int indexOfMe = siblingsAndMe.indexOf(this); + if (indexOfMe == siblingsAndMe.size() - 1) { + // last child + return null; + } + return siblingsAndMe.get(indexOfMe + 1); + } + + // --- hasSuccessor --- + syn boolean DumpNode.hasSuccessor() = successor() != null; + class TransformationTransferInformation { java.util.Map<Object, DumpNode> transformed = new java.util.HashMap<>(); java.util.Map<DumpNode, Boolean> relationTargetsUnprocessed = new java.util.HashMap<>(); } - syn String DumpAst.toPlantUml() { - StringBuilder sb = new StringBuilder(); - com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() { - @Override - public com.github.mustachejava.Binding createBinding(String name, final com.github.mustachejava.TemplateContext tc, com.github.mustachejava.Code code) { - return new com.github.mustachejava.reflect.GuardedBinding(this, name, tc, code) { - @Override - protected synchronized com.github.mustachejava.util.Wrapper getWrapper(String name, java.util.List<Object> scopes) { - com.github.mustachejava.util.Wrapper wrapper = super.getWrapper(name, scopes); - if (wrapper instanceof com.github.mustachejava.reflect.MissingWrapper) { - throw new com.github.mustachejava.MustacheException(name + " not found in " + tc); - } - return wrapper; - } - }; - } - }; - com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory(); - mf.setObjectHandler(roh); - com.github.mustachejava.Mustache m = mf.compile("dumpAst.mustache"); - m.execute(new java.io.PrintWriter(new AppendableWriter(sb)), this); - return sb.toString(); - } - syn String DumpAst.toYaml(boolean prependCreationComment) { Document doc = new Document(); doc.setRootElement(getRootNode().toYaml()); diff --git a/dumpAst/src/main/jastadd/GenerationFrontend.jadd b/dumpAst/src/main/jastadd/GenerationFrontend.jadd index 8fd24b4..fb8e735 100644 --- a/dumpAst/src/main/jastadd/GenerationFrontend.jadd +++ b/dumpAst/src/main/jastadd/GenerationFrontend.jadd @@ -342,6 +342,11 @@ public class DumpBuilder { return this; } + public DumpBuilder orderChildren() { + printConfig.setOrderChildren(true); + return this; + } + private String readVersion() { try { java.util.ResourceBundle resources = java.util.ResourceBundle.getBundle("dumpAstVersion"); diff --git a/dumpAst/src/main/jastadd/GenerationMustache.jrag b/dumpAst/src/main/jastadd/GenerationMustache.jrag new file mode 100644 index 0000000..d69f4fb --- /dev/null +++ b/dumpAst/src/main/jastadd/GenerationMustache.jrag @@ -0,0 +1,25 @@ +aspect GenerationMustache { + syn String DumpAst.toPlantUml() { + StringBuilder sb = new StringBuilder(); + com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() { + @Override + public com.github.mustachejava.Binding createBinding(String name, final com.github.mustachejava.TemplateContext tc, com.github.mustachejava.Code code) { + return new com.github.mustachejava.reflect.GuardedBinding(this, name, tc, code) { + @Override + protected synchronized com.github.mustachejava.util.Wrapper getWrapper(String name, java.util.List<Object> scopes) { + com.github.mustachejava.util.Wrapper wrapper = super.getWrapper(name, scopes); + if (wrapper instanceof com.github.mustachejava.reflect.MissingWrapper) { + throw new com.github.mustachejava.MustacheException(name + " not found in " + tc); + } + return wrapper; + } + }; + } + }; + com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory(); + mf.setObjectHandler(roh); + com.github.mustachejava.Mustache m = mf.compile("dumpAst.mustache"); + m.execute(new java.io.PrintWriter(new AppendableWriter(sb)), this); + return sb.toString(); + } +} diff --git a/dumpAst/src/main/jastadd/Navigation.jrag b/dumpAst/src/main/jastadd/Navigation.jrag index 8783503..3f04c9c 100644 --- a/dumpAst/src/main/jastadd/Navigation.jrag +++ b/dumpAst/src/main/jastadd/Navigation.jrag @@ -33,6 +33,17 @@ aspect Navigation { eq DumpNode.getDumpRelation().containingDumpNode() = this; eq DumpNode.getInvisiblePath().containingDumpNode() = this; + // --- container --- + syn DumpNode DumpNode.container() { + if (getContainerOfNormalChild() != null) { + return getContainerOfNormalChild().containingDumpNode(); + } + if (getContainerOfInner() != null) { + return getContainerOfInner().containingDumpNode(); + } + return null; + } + // --- innerVisibleNodes --- syn java.util.List<DumpNode> DumpChildNode.innerVisibleNodes() = innerNodes(true); syn java.util.List<DumpNode> DumpRelation.innerVisibleNodes() = innerNodes(true); diff --git a/dumpAst/src/main/resources/dumpAst.mustache b/dumpAst/src/main/resources/dumpAst.mustache index b15a984..9dd0d02 100644 --- a/dumpAst/src/main/resources/dumpAst.mustache +++ b/dumpAst/src/main/resources/dumpAst.mustache @@ -63,6 +63,13 @@ object "{{{labelAndTextColor}}}" as {{name}} {{#backgroundColor}}#{{{backgroundC {{/InnerDumpNodes}} {{/InvisiblePath}} {{/Invisible}} + {{#PrintConfig}}{{#orderChildren}} + {{#myChildren}} + {{#hasSuccessor}} +{{name}} -[hidden]right-> {{#successor}}{{name}}{{/successor}} + {{/hasSuccessor}} + {{/myChildren}} + {{/orderChildren}}{{/PrintConfig}} {{/DumpNodes}} {{#BuildConfig}} {{#Debug}} diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java index f7699f6..d759fbf 100644 --- a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java +++ b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java @@ -1,10 +1,14 @@ package de.tudresden.inf.st.jastadd.testDumper; +import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpAst; +import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpNode; import org.jastadd.testDumper.ast.A; import org.jastadd.testDumper.ast.B; import org.jastadd.testDumper.ast.C; import org.jastadd.testDumper.ast.Root; +import java.util.stream.Collectors; + public class TestDumperMain { public static void main(String[] args) { Root root = new Root(); @@ -29,14 +33,20 @@ public class TestDumperMain { TestUtils.ExposingDumpBuilder builder = new TestUtils.ExposingDumpBuilder(root); builder.includeAttributes("simpleAttr") - .includeNonterminalAttributes("getCalculated"); - builder.setNameMethod(n -> n.getClass().getSimpleName()); + .orderChildren() + .includeNonterminalAttributes("getCalculated") + .setNameMethod(n -> n.getClass().getSimpleName()); System.out.println(">> PlantUml"); - System.out.println(builder.build().toPlantUml()); + DumpAst dumpAst = builder.build(); + System.out.println(dumpAst.toPlantUml()); + + DumpNode node = dumpAst.getDumpNode(0); + System.out.println(node.getName()); + System.out.println(node.myChildren().stream().map(DumpNode::getName).collect(Collectors.joining(", "))); - System.out.println(">> YAML begin"); - System.out.println(builder.build().toYaml(true)); - System.out.println(">> YAML end"); +// System.out.println(">> YAML begin"); +// System.out.println(builder.build().toYaml(true)); +// System.out.println(">> YAML end"); } } diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java index fd6c961..c196d87 100644 --- a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java +++ b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java @@ -1,5 +1,7 @@ package de.tudresden.inf.st.jastadd.testDumper; +import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpAst; +import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpBuilder; import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpNode; import org.jastadd.testDumper.ast.*; import org.junit.jupiter.api.Test; @@ -60,6 +62,22 @@ public class TestSimple { assertThatMapOf(listChildren(actualRoot), "B").containsExactlyInAnyOrder(B1_NAME, B2_NAME, B3_NAME); } + @Test + public void testOrderedListChildren() { + Root root = createRoot(null, null, createB(B1_NAME), createB(B2_NAME), createB(B3_NAME)); + + List<DumpNode> nodes = TestUtils.dumpModel(root, DumpBuilder::orderChildren); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, B1_NAME, B2_NAME, B3_NAME); + + DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME); + // in grammar: DumpAst ::= [...] DumpNode* [...]; + // use getParent() twice as first returns JastAddList for DumpNode list + assertTrue(((DumpAst) actualRoot.getParent().getParent()).getPrintConfig().getOrderChildren()); + + List<DumpNode> children = actualRoot.myChildren(); + assertThat(children).extracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(B1_NAME, B2_NAME, B3_NAME); + } + @Test public void testOneOptChild() { Root root = createRoot(null, createC(C_NAME)); -- GitLab