From a985a0a51026af65e10dbcd96cff0211abbdc385 Mon Sep 17 00:00:00 2001
From: rschoene <rene.schoene@tu-dresden.de>
Date: Mon, 25 Jul 2022 18:04:17 +0200
Subject: [PATCH] 1.2.1

- testing with latest JastAdd version, and with incremental=param and tracing=flush
- handle optionals if not set
- remove erroneous print statement for child inclusion
- fix JavaDoc warnings
---
 dumpAst/src/main/jastadd/DumpAst.relast       |  4 +++
 .../src/main/jastadd/GeneratedNavigation.jrag | 13 ++++++++
 .../src/main/jastadd/GenerationBackend.jadd   | 30 +++++++++++++------
 .../st/jastadd/dumpAst/ast/DumpBuilder.java   |  9 +++---
 .../main/resources/dumpAstVersion.properties  |  4 +--
 testDumper/build.gradle                       |  3 +-
 .../inf/st/jastadd/testDumper/TestSimple.java | 13 ++++++++
 7 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/dumpAst/src/main/jastadd/DumpAst.relast b/dumpAst/src/main/jastadd/DumpAst.relast
index 337c14c..55b270d 100644
--- a/dumpAst/src/main/jastadd/DumpAst.relast
+++ b/dumpAst/src/main/jastadd/DumpAst.relast
@@ -36,6 +36,10 @@ abstract SingleChildMethod : AnalysedMethod ;
 NormalSingleChildMethod : SingleChildMethod ;
 NTASingleChildMethod : SingleChildMethod ;
 
+abstract OptChildMethod : AnalysedMethod ::= <CheckMethod:java.lang.reflect.Method> ;
+NormalOptChildMethod : OptChildMethod ;
+NTAOptChildMethod : OptChildMethod ;
+
 abstract ListChildMethod : AnalysedMethod ;
 NormalListChildMethod : ListChildMethod ;
 NTAListChildMethod : ListChildMethod ;
diff --git a/dumpAst/src/main/jastadd/GeneratedNavigation.jrag b/dumpAst/src/main/jastadd/GeneratedNavigation.jrag
index be7166a..4ef4b46 100644
--- a/dumpAst/src/main/jastadd/GeneratedNavigation.jrag
+++ b/dumpAst/src/main/jastadd/GeneratedNavigation.jrag
@@ -18,6 +18,12 @@ aspect Navigation {
   syn boolean AnalysedMethod.isSingleChildMethod() = false;
   eq SingleChildMethod.isSingleChildMethod() = true;
 
+  /** Tests if AnalysedMethod is a OptChildMethod.
+  *  @return 'true' if this is a OptChildMethod, otherwise 'false'
+  */
+  syn boolean AnalysedMethod.isOptChildMethod() = false;
+  eq OptChildMethod.isOptChildMethod() = true;
+
   /** Tests if AnalysedMethod is a ListChildMethod.
   *  @return 'true' if this is a ListChildMethod, otherwise 'false'
   */
@@ -123,6 +129,13 @@ aspect Navigation {
   eq AnalysedMethod.asSingleChildMethod() = null;
   eq SingleChildMethod.asSingleChildMethod() = this;
 
+  /** casts a AnalysedMethod into a OptChildMethod if possible.
+   *  @return 'this' cast to a OptChildMethod or 'null'
+   */
+  syn OptChildMethod AnalysedMethod.asOptChildMethod();
+  eq AnalysedMethod.asOptChildMethod() = null;
+  eq OptChildMethod.asOptChildMethod() = this;
+
   /** casts a AnalysedMethod into a ListChildMethod if possible.
    *  @return 'this' cast to a ListChildMethod or 'null'
    */
diff --git a/dumpAst/src/main/jastadd/GenerationBackend.jadd b/dumpAst/src/main/jastadd/GenerationBackend.jadd
index bf3ccf3..bef0917 100644
--- a/dumpAst/src/main/jastadd/GenerationBackend.jadd
+++ b/dumpAst/src/main/jastadd/GenerationBackend.jadd
@@ -11,7 +11,7 @@ aspect GenerationBackend {
       public boolean computed;
 
       public TransformationOptions asRelation() {
-        return fromSource(Source.RELATION, false).allowNullObjectsOnce();
+        return fromSource(Source.RELATION, false).computed(false).allowNullObjectsOnce();
       }
 
       public TransformationOptions asRoot() {
@@ -123,9 +123,19 @@ aspect GenerationBackend {
       System.out.println("for node " + obj + ", analysis was:\n" + car.prettyPrint());
     }
     for (AnalysedMethod containmentMethod : car.getContainmentMethodList()) {
-      if (containmentMethod.isSingleChildMethod()) {
-        // -- singleChild --
-        Object target = containmentMethod.getMethod().invoke(obj);
+      if (containmentMethod.isSingleChildMethod() || containmentMethod.isOptChildMethod()) {
+        // -- singleChild or optChild --
+        Object target;
+        if (containmentMethod.isOptChildMethod() && !((boolean) containmentMethod.asOptChildMethod().getCheckMethod().invoke(obj))) {
+          if (getBuildConfig().getExcludeNullNodes()) {
+            continue;
+            //target = containmentMethod.getMethod().invoke(obj);
+          } else {
+            target = null;
+          }
+        } else {
+          target = containmentMethod.getMethod().invoke(obj);
+        }
         String childName = containmentMethod.getName();
         if (!getBuildConfig().getIncludeChildMethod().shouldInclude(obj, target, childName)) {
           continue;
@@ -328,12 +338,14 @@ aspect GenerationBackend {
             case "OptChild":
               contextNameToAdd = invokeName(annotation);
               try {
-                // the annotated method is "get???Opt", but we want "get???"
+                // the annotated method is "get???Opt", but we want "get???" and "has???"
                 java.lang.reflect.Method realGetter = clazz.getMethod("get" + contextNameToAdd);
-                NormalSingleChildMethod normalSingleChildMethod = new NormalSingleChildMethod();
-                normalSingleChildMethod.setMethod(realGetter);
-                normalSingleChildMethod.setName(contextNameToAdd);
-                containmentMethodToAdd = normalSingleChildMethod;
+                java.lang.reflect.Method checkMethod = clazz.getMethod("has" + contextNameToAdd);
+                NormalOptChildMethod normalOptChildMethod = new NormalOptChildMethod();
+                normalOptChildMethod.setMethod(realGetter);
+                normalOptChildMethod.setCheckMethod(checkMethod);
+                normalOptChildMethod.setName(contextNameToAdd);
+                containmentMethodToAdd = normalOptChildMethod;
               } catch (NoSuchMethodException e) {
                 System.err.println("Could not find getter for Opt-child " + contextNameToAdd + " in " + clazzName);
                 throw new RuntimeException(e);
diff --git a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java b/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java
index 18bd976..251055a 100644
--- a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java
+++ b/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java
@@ -56,7 +56,6 @@ public class DumpBuilder {
     this.target = target;
     buildConfig = new BuildConfig();
     buildConfig.setIncludeChildMethod((parentNode, childNode, contextName) -> {
-      System.out.printf("child: %s, %s, %s%n", parentNode, childNode, contextName);
       // level 4: excluded for type? -> return no
       PatternCollection excludeOnType = buildConfig.matchExcludePatternCollection(parentNode.getClass().getSimpleName());
       if (excludeOnType != null && matches(excludeOnType.childPattern(), contextName)) {
@@ -580,7 +579,7 @@ public class DumpBuilder {
   }
 
   /**
-   * Set the method defining, what name a node has (default: n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode())).
+   * Set the method defining, what name a node has (default: {@code n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode())}).
    *
    * <p>Example:<br>
    * {@code builder.<ASTNode<?>>setNameMethod(n -> n.isA() ? "A" : "Not A")}
@@ -594,7 +593,7 @@ public class DumpBuilder {
   }
 
   /**
-   * Set the method defining, what background color a node has (default: n -> "").
+   * Set the method defining, what background color a node has (default: {@code n -> ""}).
    *
    * <p>Example:<br>
    * {@code builder.<ASTNode<?>>setBackgroundColorMethod(n -> n.isA() ? "red" : "blue")}
@@ -608,7 +607,7 @@ public class DumpBuilder {
   }
 
   /**
-   * Set the method defining, what text color a node has (default: n -> "").
+   * Set the method defining, what text color a node has (default: {@code n -> ""}).
    *
    * <p>Example:<br>
    * {@code builder.<ASTNode<?>>setTextColorMethod(n -> n.isA() ? "black" : "white")}
@@ -622,7 +621,7 @@ public class DumpBuilder {
   }
 
   /**
-   * Set the method defining, what stereotype a node has (default: n -> "").
+   * Set the method defining, what stereotype a node has (default: {@code n -> ""}).
    *
    * <p>Example:<br>
    * {@code builder.<ASTNode<?>>setStereotypeMethod(n -> n.isA() ? "MyStereoType" : "")}
diff --git a/dumpAst/src/main/resources/dumpAstVersion.properties b/dumpAst/src/main/resources/dumpAstVersion.properties
index 25bac21..7968f51 100644
--- a/dumpAst/src/main/resources/dumpAstVersion.properties
+++ b/dumpAst/src/main/resources/dumpAstVersion.properties
@@ -1,2 +1,2 @@
-#Tue Jul 05 15:14:22 CEST 2022
-version=1.2.0
+#Mon Jul 25 18:03:32 CEST 2022
+version=1.2.1
diff --git a/testDumper/build.gradle b/testDumper/build.gradle
index 1c58931..cddc1fd 100644
--- a/testDumper/build.gradle
+++ b/testDumper/build.gradle
@@ -32,6 +32,7 @@ configurations {
 dependencies {
     implementation project(':dumpAst')
     relast group: 'org.jastadd', name: 'relast', version: "${relast_version}"
+    jastadd2 "org.jastadd:jastadd2:2.3.5-dresden-6"
 
     implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
 
@@ -109,7 +110,7 @@ jastadd {
     astPackage = 'org.jastadd.testDumper.ast'
     genDir = 'src/gen/java'
     buildInfoDir = 'src/gen-res'
-    jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
+    jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all", "--incremental=param", "--tracing=cache,flush"]
 }
 
 // --- Tests ---
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 8a10b40..752e6ce 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
@@ -143,6 +143,19 @@ public class TestSimple {
     assertFalse(actualC.hasSuccessor());
   }
 
+  @Test
+  public void testNoOptChild() {
+    Root root = new Root().setName(ROOT_NAME);
+
+    List<DumpNode> nodes = TestUtils.dumpModel(root);
+    assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME);
+    DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
+    assertEquals(1, actualRoot.getNumDumpToken());
+    assertEquals(0, actualRoot.getNumDumpChildNode());
+    assertEquals(0, actualRoot.getNumDumpRelation());
+    assertThatMapOf(normalChildren(actualRoot)).isEmpty();
+  }
+
   @Test
   public void testOneOptChild() {
     Root root = createRoot(null, createC(C_NAME));
-- 
GitLab