Skip to main content
Sign in
Snippets Groups Projects
Commit 7fa94991 authored by René Schöne's avatar René Schöne
Browse files

Show null children (shown per default)

parent f8512ae0
No related branches found
No related tags found
2 merge requests!60.3.6,!5Resolve "Show "null" children in tree"
Pipeline #12735 passed
This commit is part of merge request !6. Comments created here will be created in the context of that merge request.
DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ; DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ;
rel DumpAst.RootNode -> DumpNode ; rel DumpAst.RootNode -> DumpNode ;
BuildConfig ::= GlobalPatternCollection:PatternCollection StyleInformation ExcludeTypePattern:TypePatternCollectionMapping* IncludeTypePattern:TypePatternCollectionMapping* <TypeIgnorePattern> <IncludeEmptyString:boolean> <Debug:boolean>; BuildConfig ::= StyleInformation GlobalPatternCollection:PatternCollection
ExcludeTypePattern:TypePatternCollectionMapping* IncludeTypePattern:TypePatternCollectionMapping*
<TypeIgnorePattern> <IncludeEmptyString:boolean> <ExcludeNullNodes:boolean> <Debug:boolean>;
TypePatternCollectionMapping ::= <TypeRegex> PatternCollection ; TypePatternCollectionMapping ::= <TypeRegex> PatternCollection ;
PatternCollection ::= <TokenPattern> <ChildPattern> <RelationPattern> <AttributePattern> <NonterminalAttributePattern> ; PatternCollection ::= <TokenPattern> <ChildPattern> <RelationPattern> <AttributePattern> <NonterminalAttributePattern> ;
StyleInformation ::= <NameMethod:StyleMethod> <BackgroundColorMethod:StyleMethod> <TextColorMethod:StyleMethod>; StyleInformation ::= <NameMethod:StyleMethod> <BackgroundColorMethod:StyleMethod> <TextColorMethod:StyleMethod>;
...@@ -9,7 +11,9 @@ StyleInformation ::= <NameMethod:StyleMethod> <BackgroundColorMethod:StyleMethod ...@@ -9,7 +11,9 @@ StyleInformation ::= <NameMethod:StyleMethod> <BackgroundColorMethod:StyleMethod
PrintConfig ::= <Scale:double> <Version> <OrderChildren:boolean> Header* ; PrintConfig ::= <Scale:double> <Version> <OrderChildren:boolean> Header* ;
Header ::= <Value> ; Header ::= <Value> ;
DumpNode ::= <Name> <Label> <BackgroundColor> <TextColor> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ; DumpNode ::= DumpChildNode* DumpToken* DumpRelation*
<Name> <Label> <BackgroundColor> <TextColor> <Object:Object> <Invisible:boolean>
/InvisiblePath/ ;
InnerDumpNode ; InnerDumpNode ;
rel InnerDumpNode.DumpNode <-> DumpNode.ContainerOfInner ; rel InnerDumpNode.DumpNode <-> DumpNode.ContainerOfInner ;
... ...
......
...@@ -26,11 +26,23 @@ aspect GenerationBackend { ...@@ -26,11 +26,23 @@ aspect GenerationBackend {
} }
protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj, Source source) protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj, Source source)
throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException { throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
if (obj == null) { return transform(tti, obj, source, false);
}
protected DumpNode DumpAst.transform(
TransformationTransferInformation tti, Object obj, Source source, boolean allowNullObj)
throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
if (obj == null && !allowNullObj) {
return null; return null;
} }
DumpNode node = tti.transformed.get(obj); DumpNode node;
String objClassName = obj.getClass().getSimpleName(); String objClassName;
if (obj == null) {
node = null;
objClassName = "null";
} else {
node = tti.transformed.get(obj);
objClassName = obj.getClass().getSimpleName();
}
if (node != null) { if (node != null) {
if (source == Source.RELATION) { if (source == Source.RELATION) {
return node; return node;
...@@ -47,9 +59,7 @@ aspect GenerationBackend { ...@@ -47,9 +59,7 @@ aspect GenerationBackend {
if (!node.isAstNode()) { if (!node.isAstNode()) {
return node; return node;
} }
node.setLabel(getBuildConfig().getStyleInformation().getNameMethod().get(obj)); applyStyle(node);
node.setBackgroundColor(getBuildConfig().getStyleInformation().getBackgroundColorMethod().get(obj));
node.setTextColor(getBuildConfig().getStyleInformation().getTextColorMethod().get(obj));
// do not process node further if coming from a relation // do not process node further if coming from a relation
if (source == Source.RELATION) { if (source == Source.RELATION) {
tti.relationTargetsUnprocessed.put(node, true); tti.relationTargetsUnprocessed.put(node, true);
...@@ -58,13 +68,17 @@ aspect GenerationBackend { ...@@ -58,13 +68,17 @@ aspect GenerationBackend {
if (source == Source.INVISIBLE_PARENT || !isTypeEnabled(objClassName)) { if (source == Source.INVISIBLE_PARENT || !isTypeEnabled(objClassName)) {
node.setInvisible(true); node.setInvisible(true);
} }
if (obj == null) {
// for a null object, we do not need any further analysis
return node;
}
final ClassAnalysisResult car = analyzeClass(obj.getClass()); final ClassAnalysisResult car = analyzeClass(obj.getClass());
// -- singleChild -- // -- singleChild --
for (SingleChildMethod singleChildMethod : car.singleChildMethods()) { for (SingleChildMethod singleChildMethod : car.singleChildMethods()) {
Object target = singleChildMethod.getMethod().invoke(obj); Object target = singleChildMethod.getMethod().invoke(obj);
String childName = singleChildMethod.getName(); String childName = singleChildMethod.getName();
DumpNode targetNode = transform(tti, target, nextSource(source, !isChildEnabled(objClassName, childName))); DumpNode targetNode = transform(tti, target, nextSource(source, !isChildEnabled(objClassName, childName)), !getBuildConfig().getExcludeNullNodes());
if (target != null && targetNode != null) { if (targetNode != null) {
DumpNormalChildNode normalChild = new DumpNormalChildNode(); DumpNormalChildNode normalChild = new DumpNormalChildNode();
normalChild.setName(childName); normalChild.setName(childName);
normalChild.setDumpNode(targetNode); normalChild.setDumpNode(targetNode);
...@@ -143,6 +157,13 @@ aspect GenerationBackend { ...@@ -143,6 +157,13 @@ aspect GenerationBackend {
return node; return node;
} }
private void DumpAst.applyStyle(DumpNode node) {
Object obj = node.getObject();
node.setLabel(getBuildConfig().getStyleInformation().getNameMethod().get(obj));
node.setBackgroundColor(getBuildConfig().getStyleInformation().getBackgroundColorMethod().get(obj));
node.setTextColor(getBuildConfig().getStyleInformation().getTextColorMethod().get(obj));
}
private Source DumpAst.nextSource(Source currentSource, boolean shouldBeInvisible) { private Source DumpAst.nextSource(Source currentSource, boolean shouldBeInvisible) {
return currentSource == Source.INVISIBLE_PARENT ? Source.INVISIBLE_PARENT : return currentSource == Source.INVISIBLE_PARENT ? Source.INVISIBLE_PARENT :
(shouldBeInvisible ? Source.INVISIBLE_PARENT : Source.PARENT); (shouldBeInvisible ? Source.INVISIBLE_PARENT : Source.PARENT);
...@@ -415,6 +436,10 @@ aspect GenerationBackend { ...@@ -415,6 +436,10 @@ aspect GenerationBackend {
// --- isAstNode --- // --- isAstNode ---
syn boolean DumpNode.isAstNode() { syn boolean DumpNode.isAstNode() {
if (getObject() == null) {
// this is only possible for normal child nodes, and they are ast nodes
return true;
}
Class<?> clazz = getObject().getClass(); Class<?> clazz = getObject().getClass();
for (java.lang.reflect.Method method : clazz.getMethods()) { for (java.lang.reflect.Method method : clazz.getMethods()) {
if ("init$Children".equals(method.getName()) && method.getParameterCount() == 0) { if ("init$Children".equals(method.getName()) && method.getParameterCount() == 0) {
...@@ -462,7 +487,6 @@ aspect GenerationBackend { ...@@ -462,7 +487,6 @@ aspect GenerationBackend {
} }
} }
// --- myChildren --- // --- myChildren ---
syn java.util.List<DumpNode> DumpNode.myChildren() { syn java.util.List<DumpNode> DumpNode.myChildren() {
java.util.List<DumpNode> result = new java.util.ArrayList<>(); java.util.List<DumpNode> result = new java.util.ArrayList<>();
...@@ -579,7 +603,7 @@ aspect GenerationBackend { ...@@ -579,7 +603,7 @@ aspect GenerationBackend {
static StyleInformation StyleInformation.createDefault() { static StyleInformation StyleInformation.createDefault() {
StyleInformation result = new StyleInformation(); StyleInformation result = new StyleInformation();
result.setNameMethod(n -> n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode())); result.setNameMethod(n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode()));
result.setBackgroundColorMethod(n -> ""); result.setBackgroundColorMethod(n -> "");
result.setTextColorMethod(n -> ""); result.setTextColorMethod(n -> "");
return result; return result;
... ...
......
...@@ -308,6 +308,16 @@ public class DumpBuilder { ...@@ -308,6 +308,16 @@ public class DumpBuilder {
} }
} }
public DumpBuilder excludeNullNodes() {
buildConfig.setExcludeNullNodes(true);
return this;
}
public DumpBuilder includeNullNodes() {
buildConfig.setExcludeNullNodes(false);
return this;
}
public DumpBuilder customPreamble(String option) { public DumpBuilder customPreamble(String option) {
printConfig.addHeader(new Header(option)); printConfig.addHeader(new Header(option));
return this; return this;
... ...
......
...@@ -35,7 +35,7 @@ public class TestDumperMain { ...@@ -35,7 +35,7 @@ public class TestDumperMain {
builder.includeAttributes("simpleAttr") builder.includeAttributes("simpleAttr")
.orderChildren() .orderChildren()
.includeNonterminalAttributes("getCalculated") .includeNonterminalAttributes("getCalculated")
.setNameMethod(n -> n.getClass().getSimpleName()); .setNameMethod(n -> n == null ? "null" : n.getClass().getSimpleName());
System.out.println(">> PlantUml"); System.out.println(">> PlantUml");
DumpAst dumpAst = builder.build(); DumpAst dumpAst = builder.build();
... ...
......
...@@ -31,9 +31,9 @@ public class TestSimple { ...@@ -31,9 +31,9 @@ public class TestSimple {
@Test void testChildlessNonterminal() { @Test void testChildlessNonterminal() {
Root root = createRoot(createA(A_NAME, a -> a.setD(new D())), null); Root root = createRoot(createA(A_NAME, a -> a.setD(new D())), null);
List<DumpNode> nodes = TestUtils.dumpModel(root); List<DumpNode> nodes = TestUtils.dumpModel(root);
Optional<DumpNode> optionalCDumpNode = nodes.stream().filter(n -> n.getObject() instanceof D).findFirst(); Optional<DumpNode> actualD = nodes.stream().filter(n -> n.getObject() instanceof D).findFirst();
assertTrue(optionalCDumpNode.isPresent()); assertTrue(actualD.isPresent());
assertTrue(optionalCDumpNode.get().isAstNode()); assertTrue(actualD.get().isAstNode());
} }
@Test @Test
...@@ -49,6 +49,22 @@ public class TestSimple { ...@@ -49,6 +49,22 @@ public class TestSimple {
assertThatMapOf(normalChildren(actualRoot)).containsExactlyInAnyOrder(tuple("A", A_NAME)); assertThatMapOf(normalChildren(actualRoot)).containsExactlyInAnyOrder(tuple("A", A_NAME));
} }
@Test
public void testOneNormalChildIncludeNullNodes() {
Root root = createRoot(createA(A_NAME), null);
List<DumpNode> nodes = TestUtils.dumpModel(root, DumpBuilder::includeNullNodes);
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(
ROOT_NAME, A_NAME, null, null, null, null);
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertEquals(1, actualRoot.getNumDumpToken());
assertEquals(2, actualRoot.getNumDumpChildNode());
assertEquals(0, actualRoot.getNumDumpRelation());
DumpNode actualA = TestUtils.findByName(nodes, A_NAME);
assertEquals(3, actualA.getNumDumpChildNode());
}
@Test @Test
public void testListChildren() { public void testListChildren() {
Root root = createRoot(null, null, createB(B1_NAME), createB(B2_NAME), createB(B3_NAME)); Root root = createRoot(null, null, createB(B1_NAME), createB(B2_NAME), createB(B3_NAME));
... ...
......
...@@ -156,6 +156,7 @@ public class TestUtils { ...@@ -156,6 +156,7 @@ public class TestUtils {
public static List<DumpNode> dumpModel(Object target, Consumer<DumpBuilder> options) { public static List<DumpNode> dumpModel(Object target, Consumer<DumpBuilder> options) {
ExposingDumpBuilder builder = new ExposingDumpBuilder(target); ExposingDumpBuilder builder = new ExposingDumpBuilder(target);
builder.excludeNullNodes();
options.accept(builder); options.accept(builder);
DumpAst dumpAst = builder.build(); DumpAst dumpAst = builder.build();
// let mustache run, but ignore result // let mustache run, but ignore result
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment