diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5c1e5c728453a0d42d04550490702f9ea7857a91..d3399cf3b1ba870b9d5c54978254134113d1d1b1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,7 +22,7 @@ build:
     - "./gradlew assemble"
   artifacts:
     paths:
-      - "dumpAst/src/gen"
+      - "dumpAst.base/src/gen"
     expire_in: 1 week
 
 test:
@@ -65,7 +65,7 @@ ragdoc_build:
   needs:
     - build
   script:
-    - JAVA_FILES=$(find dumpAst/src/ -name '*.java')
+    - JAVA_FILES=$(find dumpAst.base/src/ -name '*.java')
     - echo $JAVA_FILES | wc -l
     - /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES
   artifacts:
diff --git a/.gitmodules b/.gitmodules
index cc5edadc2028bc1f4db584f19862852cda5830e8..5172070ff4338a2cdf5e3b2d30184c4ddb7cb9bf 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
 [submodule "dumpAst/src/main/jastadd/mustache"]
-	path = dumpAst/src/main/jastadd/mustache
+	path = dumpAst.base/src/main/jastadd/mustache
 	url = ../mustache
diff --git a/README.md b/README.md
index 1b001cb8f7f67d2362aff1ea9f911948dbd1adde..2095d42224d2b4f05aab7d403dd5d1b996282a81 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
 # DumpAst
 
-For documentation, please see https://jastadd.pages.st.inf.tu-dresden.de/relast2uml/
+For documentation, please see https://jastadd.pages.st.inf.tu-dresden.de/dumpAst/
diff --git a/dumpAst/.gitignore b/dumpAst.base/.gitignore
similarity index 100%
rename from dumpAst/.gitignore
rename to dumpAst.base/.gitignore
diff --git a/dumpAst/build.gradle b/dumpAst.base/build.gradle
similarity index 88%
rename from dumpAst/build.gradle
rename to dumpAst.base/build.gradle
index 11c2716e20e3a033ab67f9f7bd8567489aaf5933..96fd0c021d8d68a9b5cb57b7c433a157a6896a29 100644
--- a/dumpAst/build.gradle
+++ b/dumpAst.base/build.gradle
@@ -74,21 +74,14 @@ jastadd {
     modules {
         //noinspection GroovyAssignabilityCheck
         module("DumpAst") {
-
-            java {
-                basedir "."
-                include "src/main/**/*.java"
-                include "src/gen/**/*.java"
-            }
-
             jastadd {
-                basedir ".."
-                include "dumpAst/src/main/jastadd/**/*.ast"
-                include "dumpAst/src/main/jastadd/**/*.jadd"
-                include "dumpAst/src/main/jastadd/**/*.jrag"
-                include "dumpAst/src/gen/jastadd/**/*.ast"
-                include "dumpAst/src/gen/jastadd/**/*.jadd"
-                include "dumpAst/src/gen/jastadd/**/*.jrag"
+                basedir "."
+                include "src/main/jastadd/**/*.ast"
+                include "src/main/jastadd/**/*.jadd"
+                include "src/main/jastadd/**/*.jrag"
+                include "src/gen/jastadd/**/*.ast"
+                include "src/gen/jastadd/**/*.jadd"
+                include "src/gen/jastadd/**/*.jrag"
             }
         }
     }
@@ -126,7 +119,7 @@ task fatJar(type: Jar) {
     }
 }
 
-def versionFile = "src/main/resources/${project.getName()}Version.properties"
+def versionFile = "src/main/resources/${rootProject.getName()}Version.properties"
 
 try {
     def oldProps = new Properties()
@@ -167,6 +160,8 @@ java {
 publishing {
     publications {
         maven(MavenPublication) {
+            //noinspection GroovyAssignabilityCheck
+            artifactId = 'dumpAst'
             from components.java
         }
     }
diff --git a/dumpAst.base/src/main/jastadd/ClassAnalysis.jrag b/dumpAst.base/src/main/jastadd/ClassAnalysis.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..fdd6052df4fc03bb14e50d12eb11c36ec37d5f43
--- /dev/null
+++ b/dumpAst.base/src/main/jastadd/ClassAnalysis.jrag
@@ -0,0 +1,208 @@
+aspect ClassAnalysis {
+
+  syn nta ClassAnalysisResult DumpAst.analyzeClass(java.lang.Class<?> clazz) {
+    ClassAnalysisResult result = new ClassAnalysisResult();
+    String clazzName = clazz.getSimpleName();
+    java.util.List<String> targetOrder = targetOrder(clazz);
+    methodLoop: for (java.lang.reflect.Method method : clazz.getMethods()) {
+      for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
+        String canonicalName = annotation.annotationType().getCanonicalName();
+        if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
+          String simpleName = annotation.annotationType().getSimpleName();
+          String contextNameToAdd = null;
+          AnalysedMethod containmentMethodToAdd = null;
+          switch (simpleName) {
+            case "Child":
+              contextNameToAdd = invokeName(annotation);
+              NormalSingleChildMethod singleChildMethod = new NormalSingleChildMethod();
+              singleChildMethod.setMethod(method);
+              singleChildMethod.setName(contextNameToAdd);
+              containmentMethodToAdd = singleChildMethod;
+              break;
+            case "OptChild":
+              contextNameToAdd = invokeName(annotation);
+              try {
+                // the annotated method is "get???Opt", but we want "get???" and "has???"
+                java.lang.reflect.Method realGetter = clazz.getMethod("get" + contextNameToAdd);
+                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);
+              }
+              break;
+            case "ListChild":
+              String listChildName = invokeName(annotation);
+              contextNameToAdd = listChildName;
+              NormalListChildMethod normalListChildMethod = new NormalListChildMethod();
+              normalListChildMethod.setMethod(method);
+              normalListChildMethod.setName(listChildName);
+              containmentMethodToAdd = normalListChildMethod;
+              break;
+            case "Token":
+              // heuristic for relations
+              String tokenName = invokeName(annotation);
+              if (tokenName.startsWith("_impl_")) {
+                String relationName = titleCase(tokenName.substring(6));
+                try {
+                  java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName);
+                  // normal get + token-name -> singleRelation
+                  SingleRelationMethod singleRelationMethod = new SingleRelationMethod();
+                  singleRelationMethod.setMethod(relationMethod);
+                  singleRelationMethod.setName(relationName);
+                  result.addOtherMethod(singleRelationMethod);
+                  continue;
+                } catch (NoSuchMethodException e) {
+                  // ignore, but we know this is probably not a single relation
+                }
+                // try list-relation next
+                try {
+                  java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName + "List");
+                  // normal get + token-name + "List" -> listRelation
+                  ListRelationMethod listRelationMethod = new ListRelationMethod();
+                  listRelationMethod.setMethod(relationMethod);
+                  listRelationMethod.setName(relationName);
+                  result.addOtherMethod(listRelationMethod);
+                  continue;
+                } catch (NoSuchMethodException e) {
+                  // ignore, but we know this is probably not a relation at all
+                }
+              }
+              IntrinsicTokenMethod tokenMethod = new IntrinsicTokenMethod();
+              tokenMethod.setMethod(method);
+              tokenMethod.setName(tokenName);
+              TokenMethod previousTokenMethodWithSameName = result.getTokenMethodWithName(tokenName);
+              if (method.getName().startsWith("refined__")) {
+                tokenMethod.setRefined(true);
+                // check for previous non-refined method with same name
+                if (previousTokenMethodWithSameName != null) {
+                  // replace previous method instead of adding
+                  result.setOtherMethod(tokenMethod, previousTokenMethodWithSameName.myIndex());
+                  continue;
+                }
+              } else if (previousTokenMethodWithSameName != null && previousTokenMethodWithSameName.isIntrinsicTokenMethod() && previousTokenMethodWithSameName.asIntrinsicTokenMethod().getRefined()) {
+                continue;
+              }
+              result.addOtherMethod(tokenMethod);
+              break;
+            case "Attribute":
+              if (method.getParameterCount() > 0) {
+                // ignore parametrized attributes
+                continue;
+              }
+              String attributeName = method.getName();
+              boolean isNTA = (boolean) invokeMethod("isNTA", annotation);
+              if (isNTA) {
+                // remove leading "get"
+                if (attributeName.startsWith("get")) {
+                  attributeName = attributeName.substring(3);
+                }
+                // remove trailing "List"
+                if (attributeName.endsWith("List")) {
+                  attributeName = attributeName.substring(0, attributeName.length() - 4);
+                }
+                if (Iterable.class.isAssignableFrom(method.getReturnType())) {
+                  NTAListChildMethod ntaListChildMethod = new NTAListChildMethod();
+                  ntaListChildMethod.setMethod(method);
+                  ntaListChildMethod.setName(attributeName);
+                  result.addOtherMethod(ntaListChildMethod);
+                } else {
+                  NTASingleChildMethod ntaSingleChildMethod = new NTASingleChildMethod();
+                  ntaSingleChildMethod.setMethod(method);
+                  ntaSingleChildMethod.setName(attributeName);
+                  result.addOtherMethod(ntaSingleChildMethod);
+                }
+              } else {
+                // normal attribute
+                AttributeMethod attributeMethod = new AttributeMethod();
+                attributeMethod.setMethod(method);
+                attributeMethod.setName(attributeName);
+                result.addOtherMethod(attributeMethod);
+              }
+              break;
+          }
+          if (containmentMethodToAdd != null) {
+            int indexOfContextInTarget = targetOrder.indexOf(contextNameToAdd);
+            if (indexOfContextInTarget == 0) {
+              result.getContainmentMethodList().insertChild(containmentMethodToAdd, 0);
+              continue methodLoop;
+            }
+            if (indexOfContextInTarget == targetOrder.size() - 1) {
+              result.addContainmentMethod(containmentMethodToAdd);
+              continue methodLoop;
+            }
+
+            for (int i = 0, size = result.getNumContainmentMethod(); i < size; i++) {
+              String currentContextName = result.getContainmentMethod(i).getName();
+              int indexOfCurrentInTarget = targetOrder.indexOf(currentContextName);
+              if (indexOfCurrentInTarget > indexOfContextInTarget) {
+                result.getContainmentMethodList().insertChild(containmentMethodToAdd, i);
+                continue methodLoop;
+              }
+            }
+            result.addContainmentMethod(containmentMethodToAdd);
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  TokenMethod ClassAnalysisResult.getTokenMethodWithName(String tokenName) {
+    // this can not be an attribute, since ClassAnalysisResult changes, and we do not use incremental eval
+    for (AnalysedMethod otherMethod : getOtherMethodList()) {
+      if (otherMethod.isTokenMethod()) {
+        TokenMethod tokenMethod = otherMethod.asTokenMethod();
+        if (tokenMethod.getName().equals(tokenName)) {
+          return tokenMethod;
+        }
+      }
+    }
+    return null;
+  }
+
+  inh int AnalysedMethod.myIndex();
+  eq ClassAnalysisResult.getContainmentMethod(int index).myIndex() = index;
+  eq ClassAnalysisResult.getOtherMethod(int index).myIndex() = index;
+
+  syn java.util.List<String> DumpAst.targetOrder(Class<?> clazz) {
+    for (java.lang.reflect.Constructor<?> method : clazz.getConstructors()) {
+      for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
+        String canonicalName = annotation.annotationType().getCanonicalName();
+        if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
+          String simpleName = annotation.annotationType().getSimpleName();
+          if (simpleName.equals("Constructor")) {
+            return java.util.Arrays.asList((String[]) invokeMethod("name", annotation));
+          }
+        }
+      }
+    }
+    // there is no constructor with an annotation, iff the nonterminal has no children
+    return null;
+  }
+
+  private static String DumpAst.invokeName(java.lang.annotation.Annotation annotation) {
+    return (String) invokeMethod("name", annotation);
+  }
+
+  private static Object DumpAst.invokeMethod(String name, java.lang.annotation.Annotation annotation) {
+    try {
+      return annotation.annotationType().getMethod(name).invoke(annotation);
+    } catch (java.lang.reflect.InvocationTargetException e) {
+      throw new RuntimeException(e);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(e);
+    } catch (NoSuchMethodException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  // --- astNodeAnnotationPrefix ---
+  syn String DumpAst.astNodeAnnotationPrefix() = getPackageName() + ".ASTNodeAnnotation";
+  inh String DumpNode.astNodeAnnotationPrefix();
+  eq DumpAst.getDumpNode().astNodeAnnotationPrefix() = astNodeAnnotationPrefix();
+}
diff --git a/dumpAst/src/main/jastadd/DumpAst.relast b/dumpAst.base/src/main/jastadd/DumpAst.relast
similarity index 90%
rename from dumpAst/src/main/jastadd/DumpAst.relast
rename to dumpAst.base/src/main/jastadd/DumpAst.relast
index 337c14cb1ddc8f2ba8312a5533e2db379dda320c..fcfd923c0e47bc6648f3e397ecaa99b5ff1007a7 100644
--- a/dumpAst/src/main/jastadd/DumpAst.relast
+++ b/dumpAst.base/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 ;
@@ -43,8 +47,9 @@ NTAListChildMethod : ListChildMethod ;
 SingleRelationMethod : AnalysedMethod ;
 ListRelationMethod : AnalysedMethod ;
 
+// TODO can the refine bug also happen for refined attributes?
 abstract TokenMethod : AnalysedMethod ;
-IntrinsicTokenMethod : TokenMethod ;
+IntrinsicTokenMethod : TokenMethod ::= <Refined:boolean> ;
 AttributeMethod : TokenMethod ;
 
 BuildConfig ::= StyleInformation
diff --git a/dumpAst.base/src/main/jastadd/Frontend.jrag b/dumpAst.base/src/main/jastadd/Frontend.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..f5bf7c2fa2034bffb1b8a35c347abbc7eca1cc9b
--- /dev/null
+++ b/dumpAst.base/src/main/jastadd/Frontend.jrag
@@ -0,0 +1,56 @@
+aspect Frontend {
+
+  // --- match{In,Ex}cludePatternCollection ---
+  syn PatternCollection BuildConfig.matchIncludePatternCollection(String typeName) {
+    for (TypePatternCollectionMapping mapping : getIncludeTypePatternList()) {
+      if (matches(mapping.typePattern(), typeName)) {
+        return mapping.getPatternCollection();
+      }
+    }
+    return null;
+  }
+  syn PatternCollection BuildConfig.matchExcludePatternCollection(String typeName) {
+    for (TypePatternCollectionMapping mapping : getExcludeTypePatternList()) {
+      if (matches(mapping.typePattern(), typeName)) {
+        return mapping.getPatternCollection();
+      }
+    }
+    return null;
+  }
+
+  static StyleInformation StyleInformation.createDefault() {
+    StyleInformation result = new StyleInformation();
+    result.setNameMethod(n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode()));
+    result.setBackgroundColorMethod(n -> "");
+    result.setTextColorMethod(n -> "");
+    result.setStereotypeMethod(n -> "");
+    result.setComputedColor("blue");
+    return result;
+  }
+
+  @FunctionalInterface
+  public interface StyleMethod<ASTNODE> {
+    String get(ASTNODE node);
+  }
+
+  @FunctionalInterface
+  public interface IncludeRelationMethod<ASTNODE> {
+    boolean shouldInclude(ASTNODE sourceNode, ASTNODE targetNode, String roleName);
+  }
+
+  @FunctionalInterface
+  public interface IncludeChildMethod<ASTNODE> {
+    boolean shouldInclude(ASTNODE parentNode, ASTNODE childNode, String contextName);
+  }
+
+  @FunctionalInterface
+  public interface IncludeAttributeMethod<ASTNODE> {
+    boolean shouldInclude(ASTNODE node, String attributeName, boolean isNTA, java.util.function.Supplier<Object> value);
+  }
+
+  @FunctionalInterface
+  public interface IncludeTokenMethod<ASTNODE> {
+    boolean shouldInclude(ASTNODE node, String tokenName, Object value);
+  }
+
+}
diff --git a/dumpAst/src/main/jastadd/GeneratedNavigation.jrag b/dumpAst.base/src/main/jastadd/GeneratedNavigation.jrag
similarity index 94%
rename from dumpAst/src/main/jastadd/GeneratedNavigation.jrag
rename to dumpAst.base/src/main/jastadd/GeneratedNavigation.jrag
index be7166a650a2409f5b92c914c348ca1972a64a59..4ef4b469c69254a667aa3449d9735b6a4a254bc6 100644
--- a/dumpAst/src/main/jastadd/GeneratedNavigation.jrag
+++ b/dumpAst.base/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/Imports.jadd b/dumpAst.base/src/main/jastadd/Imports.jadd
similarity index 100%
rename from dumpAst/src/main/jastadd/Imports.jadd
rename to dumpAst.base/src/main/jastadd/Imports.jadd
diff --git a/dumpAst/src/main/jastadd/GenerationMustache.jrag b/dumpAst.base/src/main/jastadd/Mustache.jrag
similarity index 98%
rename from dumpAst/src/main/jastadd/GenerationMustache.jrag
rename to dumpAst.base/src/main/jastadd/Mustache.jrag
index cf9f53455aab8a2cef109e9e8d53a27e8fac4951..40be7d934f14157fc247ec1b267eaf62defd1ca4 100644
--- a/dumpAst/src/main/jastadd/GenerationMustache.jrag
+++ b/dumpAst.base/src/main/jastadd/Mustache.jrag
@@ -1,4 +1,4 @@
-aspect GenerationMustache {
+aspect Mustache {
   syn String DumpAst.toPlantUml() {
     StringBuilder sb = new StringBuilder();
     com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() {
diff --git a/dumpAst/src/main/jastadd/Navigation.jrag b/dumpAst.base/src/main/jastadd/Navigation.jrag
similarity index 100%
rename from dumpAst/src/main/jastadd/Navigation.jrag
rename to dumpAst.base/src/main/jastadd/Navigation.jrag
diff --git a/dumpAst/src/main/jastadd/Printing.jrag b/dumpAst.base/src/main/jastadd/Printing.jrag
similarity index 93%
rename from dumpAst/src/main/jastadd/Printing.jrag
rename to dumpAst.base/src/main/jastadd/Printing.jrag
index 6ae0af30b8273ed64d20e486035ef03b912f4844..f42e6fabd2035376057f4655ce36674261d27376 100644
--- a/dumpAst/src/main/jastadd/Printing.jrag
+++ b/dumpAst.base/src/main/jastadd/Printing.jrag
@@ -43,16 +43,16 @@ aspect Printing {
 aspect Debugging {
   syn String ClassAnalysisResult.prettyPrint() {
     StringBuilder sb = new StringBuilder();
-    sb.append("ContainmentMethods:");
+    sb.append("- ContainmentMethods: ");
     for (AnalysedMethod method : getContainmentMethodList()) {
-      sb.append(method.prettyPrint()).append(",");
+      sb.append("\n  - ").append(method.prettyPrint());
     }
     if (getNumContainmentMethod() == 0) {
       sb.append("none. ");
     }
-    sb.append("other methods:");
+    sb.append("\n- Other methods: ");
     for (AnalysedMethod method : getOtherMethodList()) {
-      sb.append(method.prettyPrint()).append(",");
+      sb.append("\n  - ").append(method.prettyPrint());
     }
     if (getNumOtherMethod() == 0) {
       sb.append("none.");
diff --git a/dumpAst.base/src/main/jastadd/TemplateContext.jrag b/dumpAst.base/src/main/jastadd/TemplateContext.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..e8d5549ccd5722276c53c6063ee381610e9f57c3
--- /dev/null
+++ b/dumpAst.base/src/main/jastadd/TemplateContext.jrag
@@ -0,0 +1,113 @@
+aspect TemplateContext {
+
+  // --- debug --- (mustache has printConfig as context)
+  syn boolean PrintConfig.debug() = buildConfig().getDebug();
+
+  // --- isNull ---
+  syn boolean DumpNode.isNull() {
+    return getObject() == null;
+  }
+
+  // --- isAstNode ---
+  syn boolean DumpNode.isAstNode() {
+    if (getObject() == null) {
+      return false;
+    }
+    Class<?> clazz = getObject().getClass();
+    for (java.lang.reflect.Method method : clazz.getMethods()) {
+      if ("init$Children".equals(method.getName()) && method.getParameterCount() == 0) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // --- NTA: InvisiblePath ---
+  syn InvisiblePath DumpNode.getInvisiblePath() {
+    InvisiblePath result = new InvisiblePath();
+    for (DumpNode successor : reachableThroughInvisible()) {
+      result.addInnerRelationDumpNode(new InnerRelationDumpNode(successor));
+    }
+    return result;
+  }
+
+  // --- reachableThroughInvisible ---
+  syn java.util.List<DumpNode> DumpNode.reachableThroughInvisible() {
+    java.util.List<DumpNode> result = new java.util.ArrayList<>();
+    for (DumpChildNode childNode : getDumpChildNodeList()) {
+      for (DumpNode inner : childNode.innerNodes(false)) {
+        if (inner != null && inner.getInvisible()) {
+          result.addAll(inner.reachableThroughInvisible());
+        } else if (this.getInvisible()) {
+          result.add(inner);
+        }
+      }
+    }
+    return result;
+  }
+
+  // --- labelAndTextColor ---
+  syn String DumpNode.labelAndTextColor() {
+    if (getTextColor().isEmpty()) {
+      return getLabel();
+    } else {
+      return "<color:" + getTextColor() + ">" + getLabel() + "</color>";
+    }
+  }
+
+  // --- stereotypeList ---
+  syn String DumpNode.stereotypeList() {
+    StringBuilder sb = new StringBuilder(getManualStereotypes());
+    if (!automaticStereotypes().isEmpty()) {
+      // add automatic stereotypes, if there are any
+      if (!getManualStereotypes().isEmpty()) {
+        // add a comma between manual and automatic, if both are present
+        sb.append(",");
+      }
+      sb.append(automaticStereotypes());
+    }
+    String manualAndAutomaticStereotypes = sb.toString();
+    if (manualAndAutomaticStereotypes.isEmpty()) {
+      return "";
+    }
+    sb = new StringBuilder();
+    for (String stereotype : manualAndAutomaticStereotypes.split(",")) {
+      sb.append(" <<").append(stereotype).append(">>");
+    }
+    return sb.toString();
+  }
+  // --- manualAndAutomaticStereotypes ---
+  syn String DumpNode.automaticStereotypes() = getComputed() ? "NTA" : "";
+
+  // --- 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;
+
+  syn String DumpAst.computedColor() = getBuildConfig().getStyleInformation().getComputedColor();
+
+}
diff --git a/dumpAst/src/main/jastadd/GenerationToYaml.jrag b/dumpAst.base/src/main/jastadd/ToYaml.jrag
similarity index 97%
rename from dumpAst/src/main/jastadd/GenerationToYaml.jrag
rename to dumpAst.base/src/main/jastadd/ToYaml.jrag
index 5f3d3b26dac7c41a48564599cdf5bd80d158a0f4..0df35a8701bd1a8b4d5b93ab04d47a327ce21436 100644
--- a/dumpAst/src/main/jastadd/GenerationToYaml.jrag
+++ b/dumpAst.base/src/main/jastadd/ToYaml.jrag
@@ -1,4 +1,4 @@
-aspect GenerationToYaml {
+aspect ToYaml {
   syn String DumpAst.printYaml(boolean prependCreationComment) {
     Document doc = new Document();
     doc.setRootElement(this.toYaml(false));
@@ -240,7 +240,9 @@ aspect GenerationToYaml {
     if (value.isEmpty()) {
       return StringElement.of(value);
     }
-    return refined(value);
+    return containsAny(value, ",#[{\"\n") ?
+      StringElement.of(value.replace("\n", "\\n").replace("\"", "\\\"")) :
+      ValueElement.of(value);
   }
 
 }
diff --git a/dumpAst/src/main/jastadd/GenerationBackend.jadd b/dumpAst.base/src/main/jastadd/Transform.jadd
similarity index 50%
rename from dumpAst/src/main/jastadd/GenerationBackend.jadd
rename to dumpAst.base/src/main/jastadd/Transform.jadd
index bf3ccf366e4c433d45963bf294cb3a31d9668171..747a59b1a71a04a008a36c8f5a5b8b054b8a8e65 100644
--- a/dumpAst/src/main/jastadd/GenerationBackend.jadd
+++ b/dumpAst.base/src/main/jastadd/Transform.jadd
@@ -1,4 +1,4 @@
-aspect GenerationBackend {
+aspect Transform {
   class DumpAst {
     enum Source {
       ROOT, NORMAL, RELATION
@@ -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;
@@ -306,167 +316,6 @@ aspect GenerationBackend {
     node.setManualStereotypes(getBuildConfig().getStyleInformation().getStereotypeMethod().get(obj));
   }
 
-  syn nta ClassAnalysisResult DumpAst.analyzeClass(java.lang.Class<?> clazz) {
-    ClassAnalysisResult result = new ClassAnalysisResult();
-    String clazzName = clazz.getSimpleName();
-    java.util.List<String> targetOrder = targetOrder(clazz);
-    methodLoop: for (java.lang.reflect.Method method : clazz.getMethods()) {
-      for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
-        String canonicalName = annotation.annotationType().getCanonicalName();
-        if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
-          String simpleName = annotation.annotationType().getSimpleName();
-          String contextNameToAdd = null;
-          AnalysedMethod containmentMethodToAdd = null;
-          switch (simpleName) {
-            case "Child":
-              contextNameToAdd = invokeName(annotation);
-              NormalSingleChildMethod singleChildMethod = new NormalSingleChildMethod();
-              singleChildMethod.setMethod(method);
-              singleChildMethod.setName(contextNameToAdd);
-              containmentMethodToAdd = singleChildMethod;
-              break;
-            case "OptChild":
-              contextNameToAdd = invokeName(annotation);
-              try {
-                // the annotated method is "get???Opt", but we want "get???"
-                java.lang.reflect.Method realGetter = clazz.getMethod("get" + contextNameToAdd);
-                NormalSingleChildMethod normalSingleChildMethod = new NormalSingleChildMethod();
-                normalSingleChildMethod.setMethod(realGetter);
-                normalSingleChildMethod.setName(contextNameToAdd);
-                containmentMethodToAdd = normalSingleChildMethod;
-              } catch (NoSuchMethodException e) {
-                System.err.println("Could not find getter for Opt-child " + contextNameToAdd + " in " + clazzName);
-                throw new RuntimeException(e);
-              }
-              break;
-            case "ListChild":
-              String listChildName = invokeName(annotation);
-              contextNameToAdd = listChildName;
-              NormalListChildMethod normalListChildMethod = new NormalListChildMethod();
-              normalListChildMethod.setMethod(method);
-              normalListChildMethod.setName(listChildName);
-              containmentMethodToAdd = normalListChildMethod;
-              break;
-            case "Token":
-              // heuristic for relations
-              String tokenName = invokeName(annotation);
-              if (tokenName.startsWith("_impl_")) {
-                String relationName = titleCase(tokenName.substring(6));
-                try {
-                  java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName);
-                  // normal get + token-name -> singleRelation
-                  SingleRelationMethod singleRelationMethod = new SingleRelationMethod();
-                  singleRelationMethod.setMethod(relationMethod);
-                  singleRelationMethod.setName(relationName);
-                  result.addOtherMethod(singleRelationMethod);
-                  continue;
-                } catch (NoSuchMethodException e) {
-                  // ignore, but we know this is probably not a single relation
-                }
-                // try list-relation next
-                try {
-                  java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName + "List");
-                  // normal get + token-name + "List" -> listRelation
-                  ListRelationMethod listRelationMethod = new ListRelationMethod();
-                  listRelationMethod.setMethod(relationMethod);
-                  listRelationMethod.setName(relationName);
-                  result.addOtherMethod(listRelationMethod);
-                  continue;
-                } catch (NoSuchMethodException e) {
-                  // ignore, but we know this is probably not a relation at all
-                }
-              }
-              IntrinsicTokenMethod tokenMethod = new IntrinsicTokenMethod();
-              tokenMethod.setMethod(method);
-              tokenMethod.setName(tokenName);
-              result.addOtherMethod(tokenMethod);
-              break;
-            case "Attribute":
-              if (method.getParameterCount() > 0) {
-                // ignore parametrized attributes
-                continue;
-              }
-              String attributeName = method.getName();
-              boolean isNTA = (boolean) invokeMethod("isNTA", annotation);
-              if (isNTA) {
-                // remove leading "get"
-                if (attributeName.startsWith("get")) {
-                  attributeName = attributeName.substring(3);
-                }
-                // remove trailing "List"
-                if (attributeName.endsWith("List")) {
-                  attributeName = attributeName.substring(0, attributeName.length() - 4);
-                }
-                if (Iterable.class.isAssignableFrom(method.getReturnType())) {
-                  NTAListChildMethod ntaListChildMethod = new NTAListChildMethod();
-                  ntaListChildMethod.setMethod(method);
-                  ntaListChildMethod.setName(attributeName);
-                  result.addOtherMethod(ntaListChildMethod);
-                } else {
-                  NTASingleChildMethod ntaSingleChildMethod = new NTASingleChildMethod();
-                  ntaSingleChildMethod.setMethod(method);
-                  ntaSingleChildMethod.setName(attributeName);
-                  result.addOtherMethod(ntaSingleChildMethod);
-                }
-              } else {
-                // normal attribute
-                AttributeMethod attributeMethod = new AttributeMethod();
-                attributeMethod.setMethod(method);
-                attributeMethod.setName(attributeName);
-                result.addOtherMethod(attributeMethod);
-              }
-              break;
-          }
-          if (containmentMethodToAdd != null) {
-            int indexOfContextInTarget = targetOrder.indexOf(contextNameToAdd);
-            if (indexOfContextInTarget == 0) {
-              result.getContainmentMethodList().insertChild(containmentMethodToAdd, 0);
-              continue methodLoop;
-            }
-            if (indexOfContextInTarget == targetOrder.size() - 1) {
-              result.addContainmentMethod(containmentMethodToAdd);
-              continue methodLoop;
-            }
-
-            for (int i = 0, size = result.getNumContainmentMethod(); i < size; i++) {
-              String currentContextName = result.getContainmentMethod(i).getName();
-              int indexOfCurrentInTarget = targetOrder.indexOf(currentContextName);
-              if (indexOfCurrentInTarget > indexOfContextInTarget) {
-                result.getContainmentMethodList().insertChild(containmentMethodToAdd, i);
-                continue methodLoop;
-              }
-            }
-            result.addContainmentMethod(containmentMethodToAdd);
-          }
-        }
-      }
-    }
-    return result;
-  }
-
-  syn java.util.List<String> DumpAst.targetOrder(Class<?> clazz) {
-    for (java.lang.reflect.Constructor<?> method : clazz.getConstructors()) {
-      for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
-        String canonicalName = annotation.annotationType().getCanonicalName();
-        if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
-          String simpleName = annotation.annotationType().getSimpleName();
-          if (simpleName.equals("Constructor")) {
-            return java.util.Arrays.asList((String[]) invokeMethod("name", annotation));
-          }
-        }
-      }
-    }
-    // there is no constructor with an annotation, iff the nonterminal has no children
-    return null;
-  }
-
-  private String DumpAst.titleCase(String s) {
-    if (s.isEmpty()) {
-      return s;
-    }
-    return Character.toUpperCase(s.charAt(0)) + s.substring(1);
-  }
-
   // TODO: add new attributes for: {token,child,relation,attribute,nta}Enabled(String parentType, String name). 1) just move implementation into this attribute. 2) add include/exclude on type-level to it.
 
   // --- isTypeEnabled ---
@@ -474,24 +323,6 @@ aspect GenerationBackend {
     return !matches(getBuildConfig().typeIgnorePattern(), typeName);
   }
 
-  // --- match{In,Ex}cludePatternCollection ---
-  syn PatternCollection BuildConfig.matchIncludePatternCollection(String typeName) {
-    for (TypePatternCollectionMapping mapping : getIncludeTypePatternList()) {
-      if (matches(mapping.typePattern(), typeName)) {
-        return mapping.getPatternCollection();
-      }
-    }
-    return null;
-  }
-  syn PatternCollection BuildConfig.matchExcludePatternCollection(String typeName) {
-    for (TypePatternCollectionMapping mapping : getExcludeTypePatternList()) {
-      if (matches(mapping.typePattern(), typeName)) {
-        return mapping.getPatternCollection();
-      }
-    }
-    return null;
-  }
-
   // --- {typeIgnore,child,token,relation,attribute,nta}Pattern ---
   syn java.util.regex.Pattern BuildConfig.typeIgnorePattern() = java.util.regex.Pattern.compile(getTypeIgnorePattern());
   syn java.util.regex.Pattern PatternCollection.childPattern() = java.util.regex.Pattern.compile(getChildPattern());
@@ -506,175 +337,9 @@ aspect GenerationBackend {
     return p.matcher(input).matches();
   }
 
-  // --- debug --- (mustache has printConfig as context)
-  syn boolean PrintConfig.debug() = buildConfig().getDebug();
-
-  private static String DumpAst.invokeName(java.lang.annotation.Annotation annotation) {
-    return (String) invokeMethod("name", annotation);
-  }
-  private static Object DumpAst.invokeMethod(String name, java.lang.annotation.Annotation annotation) {
-    try {
-      return annotation.annotationType().getMethod(name).invoke(annotation);
-    } catch (java.lang.reflect.InvocationTargetException e) {
-      throw new RuntimeException(e);
-    } catch (IllegalAccessException e) {
-      throw new RuntimeException(e);
-    } catch (NoSuchMethodException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  // --- isNull ---
-  syn boolean DumpNode.isNull() {
-    return getObject() == null;
-  }
-
-  // --- isAstNode ---
-  syn boolean DumpNode.isAstNode() {
-    if (getObject() == null) {
-      return false;
-    }
-    Class<?> clazz = getObject().getClass();
-    for (java.lang.reflect.Method method : clazz.getMethods()) {
-      if ("init$Children".equals(method.getName()) && method.getParameterCount() == 0) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  // --- astNodeAnnotationPrefix ---
-  syn String DumpAst.astNodeAnnotationPrefix() = getPackageName() + ".ASTNodeAnnotation";
-  inh String DumpNode.astNodeAnnotationPrefix();
-  eq DumpAst.getDumpNode().astNodeAnnotationPrefix() = astNodeAnnotationPrefix();
-
-  // --- NTA: InvisiblePath ---
-  syn InvisiblePath DumpNode.getInvisiblePath() {
-    InvisiblePath result = new InvisiblePath();
-    for (DumpNode successor : reachableThroughInvisible()) {
-      result.addInnerRelationDumpNode(new InnerRelationDumpNode(successor));
-    }
-    return result;
-  }
-
-  // --- reachableThroughInvisible ---
-  syn java.util.List<DumpNode> DumpNode.reachableThroughInvisible() {
-    java.util.List<DumpNode> result = new java.util.ArrayList<>();
-    for (DumpChildNode childNode : getDumpChildNodeList()) {
-      for (DumpNode inner : childNode.innerNodes(false)) {
-        if (inner != null && inner.getInvisible()) {
-          result.addAll(inner.reachableThroughInvisible());
-        } else if (this.getInvisible()) {
-          result.add(inner);
-        }
-      }
-    }
-    return result;
-  }
-
-  // --- labelAndTextColor ---
-  syn String DumpNode.labelAndTextColor() {
-    if (getTextColor().isEmpty()) {
-      return getLabel();
-    } else {
-      return "<color:" + getTextColor() + ">" + getLabel() + "</color>";
-    }
-  }
-
-  // --- stereotypeList ---
-  syn String DumpNode.stereotypeList() {
-    StringBuilder sb = new StringBuilder(getManualStereotypes());
-    if (!automaticStereotypes().isEmpty()) {
-      // add automatic stereotypes, if there are any
-      if (!getManualStereotypes().isEmpty()) {
-        // add a comma between manual and automatic, if both are present
-        sb.append(",");
-      }
-      sb.append(automaticStereotypes());
-    }
-    String manualAndAutomaticStereotypes = sb.toString();
-    if (manualAndAutomaticStereotypes.isEmpty()) {
-      return "";
-    }
-    sb = new StringBuilder();
-    for (String stereotype : manualAndAutomaticStereotypes.split(",")) {
-      sb.append(" <<").append(stereotype).append(">>");
-    }
-    return sb.toString();
-  }
-  // --- manualAndAutomaticStereotypes ---
-  syn String DumpNode.automaticStereotypes() = getComputed() ? "NTA" : "";
-
-  // --- 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<>();
     int nodeCounter = 0;
   }
-
-
-  static StyleInformation StyleInformation.createDefault() {
-    StyleInformation result = new StyleInformation();
-    result.setNameMethod(n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode()));
-    result.setBackgroundColorMethod(n -> "");
-    result.setTextColorMethod(n -> "");
-    result.setStereotypeMethod(n -> "");
-    result.setComputedColor("blue");
-    return result;
-  }
-
-  syn String DumpAst.computedColor() = getBuildConfig().getStyleInformation().getComputedColor();
-
-  @FunctionalInterface
-  public interface StyleMethod<ASTNODE> {
-    String get(ASTNODE node);
-  }
-
-  @FunctionalInterface
-  public interface IncludeRelationMethod<ASTNODE> {
-    boolean shouldInclude(ASTNODE sourceNode, ASTNODE targetNode, String roleName);
-  }
-
-  @FunctionalInterface
-  public interface IncludeChildMethod<ASTNODE> {
-    boolean shouldInclude(ASTNODE parentNode, ASTNODE childNode, String contextName);
-  }
-
-  @FunctionalInterface
-  public interface IncludeAttributeMethod<ASTNODE> {
-    boolean shouldInclude(ASTNODE node, String attributeName, boolean isNTA, java.util.function.Supplier<Object> value);
-  }
-
-  @FunctionalInterface
-  public interface IncludeTokenMethod<ASTNODE> {
-    boolean shouldInclude(ASTNODE node, String tokenName, Object value);
-  }
 }
diff --git a/dumpAst/src/main/jastadd/GenerationCommon.jrag b/dumpAst.base/src/main/jastadd/Util.jrag
similarity index 78%
rename from dumpAst/src/main/jastadd/GenerationCommon.jrag
rename to dumpAst.base/src/main/jastadd/Util.jrag
index a05412d3eba8dbf7732e1f364c3664304db7d23a..32c0ab008028cd8fc2b9b3aa132b94a942067f21 100644
--- a/dumpAst/src/main/jastadd/GenerationCommon.jrag
+++ b/dumpAst.base/src/main/jastadd/Util.jrag
@@ -1,4 +1,4 @@
-aspect GenerationCommon {
+aspect Util {
   // --- find{In,Ex}cludePatternCollection ---
   syn PatternCollection BuildConfig.findIncludePatternCollection(String typeRegex) {
     for (TypePatternCollectionMapping mapping : getIncludeTypePatternList()) {
@@ -8,6 +8,7 @@ aspect GenerationCommon {
     }
     return null;
   }
+
   syn PatternCollection BuildConfig.findExcludePatternCollection(String typeRegex) {
     for (TypePatternCollectionMapping mapping : getExcludeTypePatternList()) {
       if (mapping.getTypeRegex().equals(typeRegex)) {
@@ -16,4 +17,11 @@ aspect GenerationCommon {
     }
     return null;
   }
+
+  private String DumpAst.titleCase(String s) {
+    if (s.isEmpty()) {
+      return s;
+    }
+    return Character.toUpperCase(s.charAt(0)) + s.substring(1);
+  }
 }
diff --git a/dumpAst/src/main/jastadd/mustache b/dumpAst.base/src/main/jastadd/mustache
similarity index 100%
rename from dumpAst/src/main/jastadd/mustache
rename to dumpAst.base/src/main/jastadd/mustache
diff --git a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java b/dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java
similarity index 99%
rename from dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java
rename to dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java
index 18bd97671bdcf3c61793f4619c3fed393a81659a..251055a5f7a014c9225f39ba16721826622cbd9e 100644
--- a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/DumpBuilder.java
+++ b/dumpAst.base/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/java/de/tudresden/inf/st/jastadd/dumpAst/ast/Dumper.java b/dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/Dumper.java
similarity index 100%
rename from dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/Dumper.java
rename to dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/Dumper.java
diff --git a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamBooleanSetting.java b/dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamBooleanSetting.java
similarity index 100%
rename from dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamBooleanSetting.java
rename to dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamBooleanSetting.java
diff --git a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamStringSetting.java b/dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamStringSetting.java
similarity index 100%
rename from dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamStringSetting.java
rename to dumpAst.base/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/ast/SkinParamStringSetting.java
diff --git a/dumpAst/src/main/resources/dumpAst.mustache b/dumpAst.base/src/main/resources/dumpAst.mustache
similarity index 100%
rename from dumpAst/src/main/resources/dumpAst.mustache
rename to dumpAst.base/src/main/resources/dumpAst.mustache
diff --git a/dumpAst.base/src/main/resources/dumpAstVersion.properties b/dumpAst.base/src/main/resources/dumpAstVersion.properties
new file mode 100644
index 0000000000000000000000000000000000000000..dd0adf1695b118450b79cf06a51d33c090308347
--- /dev/null
+++ b/dumpAst.base/src/main/resources/dumpAstVersion.properties
@@ -0,0 +1,2 @@
+#Tue Sep 06 14:11:59 CEST 2022
+version=1.2.2
diff --git a/featureTest/.gitignore b/dumpAst.prototyping/.gitignore
similarity index 100%
rename from featureTest/.gitignore
rename to dumpAst.prototyping/.gitignore
diff --git a/featureTest/build.gradle b/dumpAst.prototyping/build.gradle
similarity index 80%
rename from featureTest/build.gradle
rename to dumpAst.prototyping/build.gradle
index 21ca23ab47a643426503e7d188a03ac2add312b9..acbb60c1fdd421b6ccb378a41147a73727320001 100644
--- a/featureTest/build.gradle
+++ b/dumpAst.prototyping/build.gradle
@@ -31,9 +31,11 @@ configurations {
 }
 
 dependencies {
-    implementation project(":dumpAst")
+    implementation project(":dumpAst.base")
     jastadd2 group: 'org.jastadd', name: 'jastadd2', version: '2.3.5-dresden'
     relast group: 'org.jastadd', name: 'relast', version: "${relast_version}"
+    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.3'
+    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.13.3'
 
     implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
 }
@@ -73,13 +75,13 @@ jastadd {
         //noinspection GroovyAssignabilityCheck
         module("featureTest") {
             jastadd {
-                basedir ".."
-                include "featureTest/src/main/jastadd/**/*.ast"
-                include "featureTest/src/main/jastadd/**/*.jadd"
-                include "featureTest/src/main/jastadd/**/*.jrag"
-                include "featureTest/src/gen/jastadd/**/*.ast"
-                include "featureTest/src/gen/jastadd/**/*.jadd"
-                include "featureTest/src/gen/jastadd/**/*.jrag"
+                basedir "."
+                include "src/main/jastadd/**/*.ast"
+                include "src/main/jastadd/**/*.jadd"
+                include "src/main/jastadd/**/*.jrag"
+                include "src/gen/jastadd/**/*.ast"
+                include "src/gen/jastadd/**/*.jadd"
+                include "src/gen/jastadd/**/*.jrag"
             }
         }
     }
diff --git a/featureTest/src/main/jastadd/featureTest.jrag b/dumpAst.prototyping/src/main/jastadd/featureTest.jrag
similarity index 75%
rename from featureTest/src/main/jastadd/featureTest.jrag
rename to dumpAst.prototyping/src/main/jastadd/featureTest.jrag
index 9a158c1b6d03df5db880aa7ab63b373bc798e6a4..a12910b9685279dc1c8da1342d4c82be5615f107 100644
--- a/featureTest/src/main/jastadd/featureTest.jrag
+++ b/dumpAst.prototyping/src/main/jastadd/featureTest.jrag
@@ -1,4 +1,8 @@
 aspect GrammarGlobal {
+
+  refine @com.fasterxml.jackson.annotation.JsonGetter("id") public String Nameable.getName() {
+    return refined();
+  }
   syn A C.getCalculated() {
     A result = new A();
     result.setName("Calculated-" + getName());
@@ -34,6 +38,8 @@ aspect GrammarGlobal {
   syn int Root.simpleAttr() = 42;
   syn A Root.referenceAttr() = getA();
 
+  syn String Nameable.fancyName() = getName() + ", but fancy!";
+
   syn boolean ASTNode.isA() = false;
   eq A.isA() = true;
 
@@ -41,6 +47,17 @@ aspect GrammarGlobal {
   B contributes this to Root.collectBs();
   C contributes nta getAlsoCalculatedList() to Root.collectBs();
   C contributes nta getAlsoCalculatedListNewSyntax() to Root.collectBs();
+
+  inh Root A.root();
+  eq Root.getChild().root() = this;
+
+  syn nta B A.AAA() {
+    B result = new B();
+    result.setMaybeC(root().getC());
+    return result;
+  }
+
+  public static int ASTNode.counter;
 }
 
 aspect GrammarTypeLevel {
@@ -51,3 +68,7 @@ aspect GrammarTypeLevel {
     return result;
   }
 }
+
+aspect Refining {
+  refine GrammarGlobal eq Nameable.fancyName() = refined() + " and more!";
+}
diff --git a/featureTest/src/main/jastadd/featureTest.relast b/dumpAst.prototyping/src/main/jastadd/featureTest.relast
similarity index 95%
rename from featureTest/src/main/jastadd/featureTest.relast
rename to dumpAst.prototyping/src/main/jastadd/featureTest.relast
index fa1c50ee8d1848f9aaa64306bc75ef70c89f8587..7e108fe9f1949e8bdffd152e20c379b3635f14cb 100644
--- a/featureTest/src/main/jastadd/featureTest.relast
+++ b/dumpAst.prototyping/src/main/jastadd/featureTest.relast
@@ -1,5 +1,5 @@
 // testcases with global inclusion/exclusion
-Nameable ::= <Name> ;
+abstract Nameable ::= <Name> ;
 Root : Nameable ::= A B* [C];
 A : Nameable ::= B [MyC:C] [D];
 B : Nameable ::= <OtherValue> ;
diff --git a/featureTest/src/main/java/de/tudresden/inf/st/jastadd/featureTest/FeatureTestMain.java b/dumpAst.prototyping/src/main/java/de/tudresden/inf/st/jastadd/featureTest/FeatureTestMain.java
similarity index 72%
rename from featureTest/src/main/java/de/tudresden/inf/st/jastadd/featureTest/FeatureTestMain.java
rename to dumpAst.prototyping/src/main/java/de/tudresden/inf/st/jastadd/featureTest/FeatureTestMain.java
index cd6436ba24f777b8c1b213983286d06018dcbc97..bc1d3729b387006b105e9b23a1670c4c818706e9 100644
--- a/featureTest/src/main/java/de/tudresden/inf/st/jastadd/featureTest/FeatureTestMain.java
+++ b/dumpAst.prototyping/src/main/java/de/tudresden/inf/st/jastadd/featureTest/FeatureTestMain.java
@@ -2,10 +2,7 @@ package de.tudresden.inf.st.jastadd.featureTest;
 
 import de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper;
 import de.tudresden.inf.st.jastadd.dumpAst.ast.SkinParamBooleanSetting;
-import org.jastadd.featureTest.ast.A;
-import org.jastadd.featureTest.ast.B;
-import org.jastadd.featureTest.ast.C;
-import org.jastadd.featureTest.ast.Root;
+import org.jastadd.featureTest.ast.*;
 
 import java.io.IOException;
 import java.nio.file.Path;
@@ -23,29 +20,29 @@ public class FeatureTestMain {
     root.setName("Root1");
     A a = new A().setName("A2");
     a.setB(new B().setName("B2.1"));
-    a.setMyC(new C().setName("C2.1"));
-    B b1 = new B().setName("B3");
-    C c = new C().setName("C4");
-    c.setA(new A().setName("A4.1").setB(new B().setName("B4.1.1")));
-    c.setRawReference(a);
-    b1.setOneA(a);
-    B b2 = new B().setName("B5");
-    C myC = new C().setName("C6");
-    c.setA(new A().setName("A6.1").setB(new B().setName("B6.1.1")));
-    a.setMyC(myC);
+//    a.setMyC(new C().setName("C2.1"));
+//    B b1 = new B().setName("B3").setOtherValue("some long text");
+//    C c = new C().setName("C4");
+//    c.setA(new A().setName("A4.1").setB(new B().setName("B4.1.1")));
+//    c.setRawReference(a);
+//    b1.setOneA(a);
+//    B b2 = new B().setName("B5").setOtherValue("#ff00ff");
+//    C myC = new C().setName("C6");
+//    c.setA(new A().setName("A6.1").setB(new B().setName("B6.1.1")));
+//    a.setMyC(myC);
     root.setA(a);
-    root.addB(b1);
-    root.addB(b2);
-    root.setC(c);
+//    root.addB(b1);
+//    root.addB(b2);
+//    root.setC(c);
 
     Path pathToYaml = Paths.get("featureTest.yml");
     Path pathToPng = Paths.get("featureTest.png");
     Path pathToSvg = Paths.get("featureTest.svg");
-    Path pathToPdf = Paths.get("featureTest.pdf");
     Dumper
 //        .read(null)
         .read(root)
 //        .customPreamble("hide empty members")
+        .enableDebug()
         .customPreamble("title My fancy title")
         .includeChildWhen((parentNode, childNode, contextName) -> {
           if (parentNode instanceof A && ((A) parentNode).getName().equals("A2")) {
@@ -61,17 +58,19 @@ public class FeatureTestMain {
             case "collectBs":
             case "Calculated":
             case "AlsoCalculatedListNewSyntax":
+            case "AAA":
+            case "fancyName":
               return true;
             default:
               return false;
           }
         })
         .skinParam(SkinParamBooleanSetting.Shadowing, false)
+        .setNameMethod(node -> node.getClass().getSimpleName() + ASTNode.counter++)
 //        .enableRelationWithRank()
         .dumpAsYaml(pathToYaml, true)
         .dumpAsPNG(pathToPng)
         .dumpAsSVG(pathToSvg)
-        .dumpAsPDF(pathToPdf)
         .dumpAsSource(Paths.get("featureTest.puml"))
     ;
   }
diff --git a/testDumper/.gitignore b/dumpAst.tests/.gitignore
similarity index 100%
rename from testDumper/.gitignore
rename to dumpAst.tests/.gitignore
diff --git a/testDumper/build.gradle b/dumpAst.tests/build.gradle
similarity index 80%
rename from testDumper/build.gradle
rename to dumpAst.tests/build.gradle
index 1c589314ae9434afb054c922504521320a64174e..8ddde1f3bc7be2488788ac8afec2829c8c6441f6 100644
--- a/testDumper/build.gradle
+++ b/dumpAst.tests/build.gradle
@@ -30,8 +30,9 @@ configurations {
 }
 
 dependencies {
-    implementation project(':dumpAst')
+    implementation project(':dumpAst.base')
     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'
 
@@ -75,21 +76,14 @@ jastadd {
     modules {
         //noinspection GroovyAssignabilityCheck
         module("testDumper") {
-
-            java {
-                basedir ".."
-                include "testDumper/src/main/**/*.java"
-                include "testDumper/src/gen/**/*.java"
-            }
-
             jastadd {
-                basedir ".."
-                include "testDumper/src/main/jastadd/**/*.ast"
-                include "testDumper/src/main/jastadd/**/*.jadd"
-                include "testDumper/src/main/jastadd/**/*.jrag"
-                include "testDumper/src/gen/jastadd/**/*.ast"
-                include "testDumper/src/gen/jastadd/**/*.jadd"
-                include "testDumper/src/gen/jastadd/**/*.jrag"
+                basedir "."
+                include "src/main/jastadd/**/*.ast"
+                include "src/main/jastadd/**/*.jadd"
+                include "src/main/jastadd/**/*.jrag"
+                include "src/gen/jastadd/**/*.ast"
+                include "src/gen/jastadd/**/*.jadd"
+                include "src/gen/jastadd/**/*.jrag"
             }
         }
     }
@@ -109,7 +103,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/main/jastadd/testDumper.jrag b/dumpAst.tests/src/main/jastadd/testDumper.jrag
similarity index 100%
rename from testDumper/src/main/jastadd/testDumper.jrag
rename to dumpAst.tests/src/main/jastadd/testDumper.jrag
diff --git a/testDumper/src/main/jastadd/testDumper.relast b/dumpAst.tests/src/main/jastadd/testDumper.relast
similarity index 100%
rename from testDumper/src/main/jastadd/testDumper.relast
rename to dumpAst.tests/src/main/jastadd/testDumper.relast
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestComplex.java b/dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestComplex.java
similarity index 100%
rename from testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestComplex.java
rename to dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestComplex.java
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java b/dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java
similarity index 100%
rename from testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java
rename to dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestIncluded.java b/dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestIncluded.java
similarity index 100%
rename from testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestIncluded.java
rename to dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestIncluded.java
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java b/dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java
similarity index 96%
rename from testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java
rename to dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java
index 8a10b40c290454c154ea0c1ab9d978d279e96952..752e6ce02448417115b276d81152217514769ea8 100644
--- a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java
+++ b/dumpAst.tests/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));
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel3.java b/dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel3.java
similarity index 100%
rename from testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel3.java
rename to dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel3.java
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel4.java b/dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel4.java
similarity index 100%
rename from testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel4.java
rename to dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestTypeLevel4.java
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestUtils.java b/dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestUtils.java
similarity index 100%
rename from testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestUtils.java
rename to dumpAst.tests/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestUtils.java
diff --git a/dumpAst/src/main/resources/dumpAstVersion.properties b/dumpAst/src/main/resources/dumpAstVersion.properties
deleted file mode 100644
index 25bac2189f8190c21fcbba00fca7f517f0f99f4f..0000000000000000000000000000000000000000
--- a/dumpAst/src/main/resources/dumpAstVersion.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-#Tue Jul 05 15:14:22 CEST 2022
-version=1.2.0
diff --git a/pages/docs/adding.md b/pages/docs/adding.md
index 6b5c91c5f7cb6a63f35157df466500b4adf4e9c3..2e2f9a84375a501e95467de1af6bd37e7f53d265 100644
--- a/pages/docs/adding.md
+++ b/pages/docs/adding.md
@@ -1,6 +1,6 @@
 # Add DumpAst to your project
 
-Check the [package overview page](https://git-st.inf.tu-dresden.de/jastadd/relast2uml/-/packages) to find the latest versions of the individual packages.
+Check the [package overview page](https://git-st.inf.tu-dresden.de/jastadd/dumpAst/-/packages) to find the latest versions of the individual packages.
 
 To use `dumpAst`, adjust your `build.gradle` as follows.
 
@@ -25,20 +25,20 @@ dependencies {
 
 ## Build from source (not recommended)
 
-If you want to build the tools of `DumpAst` from source, first build the jar from the [repository](https://git-st.inf.tu-dresden.de/jastadd/relast2uml).
+If you want to build the tools of `DumpAst` from source, first build the jar from the [repository](https://git-st.inf.tu-dresden.de/jastadd/dumpAst).
 The normal jar does not suffice, as it lacks the information on needed dependencies.
 
 ```bash
-git clone https://git-st.inf.tu-dresden.de/jastadd/relast2uml.git
-cd relast2uml
+git clone https://git-st.inf.tu-dresden.de/jastadd/dumpAst.git
+cd dumpAst
 ./gradlew fatJar
-ls dumpAst/build/libs/
+ls dumpAst.base/build/libs/
 ```
 
 This jar can then be copied to your project.
 
 ```bash
-cp dumpAst/build/libs/dumpAst-<version>.jar ../your-project/libs/dumpAst.jar
+cp dumpAst.base/build/libs/dumpAst.base-fatJar-<version>.jar ../your-project/libs/dumpAst.jar
 cd ../your-project/
 ```
 
diff --git a/pages/docs/index.md b/pages/docs/index.md
index e8f11ced151c84d6105f804427ae7f40cd6901ac..0910060203c01660960cf1904dcb8fe0a5ee3537 100644
--- a/pages/docs/index.md
+++ b/pages/docs/index.md
@@ -1,6 +1,6 @@
 # DumpAst
 
-The tool called `DumpAst` ([see in repo](https://git-st.inf.tu-dresden.de/jastadd/relast2uml)) is used to create a snapshot of an AST and visualize it.
+The tool called `DumpAst` ([see in repo](https://git-st.inf.tu-dresden.de/jastadd/dumpAst)) is used to create a snapshot of an AST and visualize it.
 
 ![](img/dumpAst.png)
 
diff --git a/pages/mkdocs.yml b/pages/mkdocs.yml
index ae9514a5623852167e6414dc757c2f8ae28fba5e..ac59250d32152419ed9a44f44d83207f2d954397 100644
--- a/pages/mkdocs.yml
+++ b/pages/mkdocs.yml
@@ -1,5 +1,5 @@
 site_name: DumpAst
-repo_url: https://git-st.inf.tu-dresden.de/jastadd/relast2uml
+repo_url: https://git-st.inf.tu-dresden.de/jastadd/dumpAst
 site_dir: ../public
 
 nav:
diff --git a/settings.gradle b/settings.gradle
index b5b5e2aba025ed461a508cd5fb5846993f43d7f7..7fd9b64b29629f9b5e2fc5fd0b275433da5cb4f5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -4,8 +4,8 @@ pluginManagement {
     }
 }
 
-rootProject.name = 'relast2uml'
+rootProject.name = 'dumpAst'
 
-include 'dumpAst'
-include 'testDumper'
-include 'featureTest'
+include 'dumpAst.base'
+include 'dumpAst.tests'
+include 'dumpAst.prototyping'