From 5611db4dc29d6347e5283de43bfc60e38c6c267d Mon Sep 17 00:00:00 2001
From: rschoene <rene.schoene@tu-dresden.de>
Date: Sat, 26 Sep 2020 12:41:47 +0200
Subject: [PATCH] WIP dumpAst 0.3.2

- working on dumping yaml
---
 .gitmodules                                   |  3 +
 dumpAst/build.gradle                          |  6 +-
 dumpAst/src/main/jastadd/DumpAst.relast       |  2 +
 dumpAst/src/main/jastadd/Generation.jadd      | 63 +++++++++++++++++--
 dumpAst/src/main/jastadd/Navigation.jrag      |  4 ++
 dumpAst/src/main/jastadd/mustache             |  1 +
 testDumper/build.gradle                       |  2 +-
 .../st/jastadd/testDumper/TestDumperMain.java | 41 ++++++++++++
 8 files changed, 115 insertions(+), 7 deletions(-)
 create mode 160000 dumpAst/src/main/jastadd/mustache
 create mode 100644 testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java

diff --git a/.gitmodules b/.gitmodules
index 3c84ce1..a8b57b0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "relast.preprocessor"]
 	path = relast.preprocessor
 	url = ../relast-preprocessor.git
+[submodule "dumpAst/src/main/jastadd/mustache"]
+	path = dumpAst/src/main/jastadd/mustache
+	url = ../mustache
diff --git a/dumpAst/build.gradle b/dumpAst/build.gradle
index 9580ac1..84b5e89 100644
--- a/dumpAst/build.gradle
+++ b/dumpAst/build.gradle
@@ -61,6 +61,7 @@ test {
 }
 
 File dumpAstGrammar = file('./src/main/jastadd/DumpAst.relast')
+File mustacheGrammar = file('./src/main/jastadd/mustache/Mustache.relast')
 
 task relast(type: JavaExec) {
     group = 'Build'
@@ -77,7 +78,7 @@ task relast(type: JavaExec) {
     args = [
             "../libs/relast.jar",
             dumpAstGrammar,
-//            "./src/main/jastadd/MustacheNodes.relast",
+            mustacheGrammar,
             "--listClass=java.util.ArrayList",
             "--jastAddList=JastAddList",
             "--useJastAddNames",
@@ -87,7 +88,8 @@ task relast(type: JavaExec) {
     ]
 
     inputs.files(file("../libs/relast.jar"),
-            dumpAstGrammar)
+            dumpAstGrammar,
+            mustacheGrammar)
     outputs.files(file("./src/gen/jastadd/DumpAst.ast"),
             file("./src/gen/jastadd/DumpAst.jadd"),
             file("./src/gen/jastadd/DumpAstRefResolver.jadd"),
diff --git a/dumpAst/src/main/jastadd/DumpAst.relast b/dumpAst/src/main/jastadd/DumpAst.relast
index c1b1ed9..e1ca0cd 100644
--- a/dumpAst/src/main/jastadd/DumpAst.relast
+++ b/dumpAst/src/main/jastadd/DumpAst.relast
@@ -1,4 +1,6 @@
 DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ;
+rel DumpAst.RootNode -> DumpNode ;
+
 BuildConfig ::= <TypeIgnore> <TokenIgnore> <ChildIgnore> <AttributeInclude> <NonterminalAttributeInclude> <RelationIgnore> <IncludeEmptyString:boolean> <Debug:boolean> ;
 PrintConfig ::= <Scale:double> <Version> Header* ;
 Header ::= <Value> ;
diff --git a/dumpAst/src/main/jastadd/Generation.jadd b/dumpAst/src/main/jastadd/Generation.jadd
index 111d767..f0e7dc5 100644
--- a/dumpAst/src/main/jastadd/Generation.jadd
+++ b/dumpAst/src/main/jastadd/Generation.jadd
@@ -180,8 +180,8 @@ import java.lang.String;aspect GenerationFrontend {
       return this;
     }
 
-    public DumpBuilder dumpAsYaml(java.nio.file.Path destination) throws java.io.IOException {
-      String content = build().toYaml();
+    public DumpBuilder dumpAsYaml(java.nio.file.Path destination, boolean prependCreationComment) throws java.io.IOException {
+      String content = build().toYaml(prependCreationComment);
       try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
         writer.write(content);
       }
@@ -201,6 +201,7 @@ aspect GenerationBackend {
   protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj)
       throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
     DumpNode result = transform(tti, obj, Source.ROOT);
+    setRootNode(result);
     // post-process relationTargetsUnprocessed
     boolean someAreUnprocessed = true;
     while (someAreUnprocessed) {
@@ -538,8 +539,62 @@ aspect GenerationBackend {
     return sb.toString();
   }
 
-  syn String DumpAst.toYaml() {
-    return "TODO :)";
+  syn String DumpAst.toYaml(boolean prependCreationComment) {
+    Document doc = new Document();
+    doc.setRootElement(getRootNode().toYaml());
+    return doc.prettyPrint(prependCreationComment);
+  }
+
+  syn MappingElement DumpNode.toYaml() {
+    MappingElement result = new MappingElement();
+    // tokens are key-value-pairs
+    for (DumpToken token : getDumpTokenList()) {
+      if (token.isDumpValueToken()) {
+        result.put(cleanLabel(token.label()), makeValueElement(token.asDumpValueToken().getValue()));
+      } else {
+        result.put(cleanLabel(token.label()), token.asDumpReferenceToken().getValue().toYaml());
+      }
+    }
+    // children
+    for (DumpChildNode child : getDumpChildNodeList()) {
+      ListElement list = new ListElement();
+      for (DumpNode inner : child.innerNodes(true)) {
+        list.add(inner.toYaml());
+      }
+      if (child.isList()) {
+        result.put(cleanLabel(child.label()), list);
+      } else if (list.getNumElement() == 1) {
+        result.put(cleanLabel(child.label()), list.getElement(0));
+      }
+    }
+    // relations
+    for (DumpRelation relation : getDumpRelationList()) {
+      ListElement list = new ListElement();
+      for (DumpNode inner : relation.innerNodes(true)) {
+        list.add(inner.toYaml());
+      }
+      if (relation.isList()) {
+        result.put(cleanLabel(relation.label()), list);
+      } else if (list.getNumElement() == 1) {
+        result.put(cleanLabel(relation.label()), list.getElement(0));
+      }
+    }
+    return result;
+  }
+
+  private static ComplexElement ASTNode.HELPER_COMPLEX_ELEMENT = new MappingElement();
+  protected static Element ASTNode.makeValueElement(Object obj) {
+    if (obj instanceof Integer) {
+      return ValueElement.of((int) obj);
+    } else if (obj instanceof Boolean) {
+      return ValueElement.of((boolean) obj);
+    } else {
+      return HELPER_COMPLEX_ELEMENT.makeStringElement(obj.toString());
+    }
+  }
+
+  private String DumpNode.cleanLabel(String originalLabel) {
+    return originalLabel.replace("()", "");
   }
 
   public class AppendableWriter extends java.io.Writer {
diff --git a/dumpAst/src/main/jastadd/Navigation.jrag b/dumpAst/src/main/jastadd/Navigation.jrag
index e03dbf3..0f4687d 100644
--- a/dumpAst/src/main/jastadd/Navigation.jrag
+++ b/dumpAst/src/main/jastadd/Navigation.jrag
@@ -13,6 +13,10 @@ aspect Navigation {
   syn DumpValueToken DumpToken.asDumpValueToken() = null;
   eq DumpValueToken.asDumpValueToken() = this;
 
+  // --- asDumpReferenceToken ---
+  syn DumpReferenceToken DumpToken.asDumpReferenceToken() = null;
+  eq DumpReferenceToken.asDumpReferenceToken() = this;
+
   // --- buildConfig ---
   inh BuildConfig DumpNode.buildConfig();
   eq DumpAst.getChild().buildConfig() = getBuildConfig();
diff --git a/dumpAst/src/main/jastadd/mustache b/dumpAst/src/main/jastadd/mustache
new file mode 160000
index 0000000..c10bed0
--- /dev/null
+++ b/dumpAst/src/main/jastadd/mustache
@@ -0,0 +1 @@
+Subproject commit c10bed0d03e3fa18b8133ce1de48de7646899615
diff --git a/testDumper/build.gradle b/testDumper/build.gradle
index 9980fef..d178652 100644
--- a/testDumper/build.gradle
+++ b/testDumper/build.gradle
@@ -13,7 +13,7 @@ buildscript {
 }
 
 dependencies {
-    runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
+//    runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
 
     testImplementation project(':dumpAst')
     testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0'
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
new file mode 100644
index 0000000..fc3d4c8
--- /dev/null
+++ b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java
@@ -0,0 +1,41 @@
+package de.tudresden.inf.st.jastadd.testDumper;
+
+import org.jastadd.testDumper.ast.A;
+import org.jastadd.testDumper.ast.B;
+import org.jastadd.testDumper.ast.C;
+import org.jastadd.testDumper.ast.Root;
+
+public class TestDumperMain {
+  public static void main(String[] args) {
+    Root root = new Root();
+    root.setName("Root1");
+    A a = new A();
+    a.setName("A2");
+    B b1 = new B();
+    b1.setName("B3");
+    C c = new C();
+    c.setName("C4");
+    c.setRawReference(a);
+    b1.setOneA(a);
+    B b2 = new B();
+    b2.setName("B5");
+    C myC = new C();
+    myC.setName("C6");
+    a.setMyC(myC);
+    root.setA(a);
+    root.addB(b1);
+    root.addB(b2);
+    root.setC(c);
+
+    TestUtils.ExposingDumpBuilder builder = new TestUtils.ExposingDumpBuilder(root);
+    builder.includeAttributes("simpleAttr")
+        .includeNonterminalAttributes("getCalculated");
+
+    System.out.println(">> PlantUml");
+    System.out.println(builder.build().toPlantUml());
+
+    System.out.println(">> YAML begin");
+    System.out.println(builder.build().toYaml(true));
+    System.out.println(">> YAML end");
+  }
+}
-- 
GitLab