Skip to content
Snippets Groups Projects
Commit b9eff203 authored by René Schöne's avatar René Schöne
Browse files

Merge branch '8-optionally-remove-identity-from-nodes' into 'dev'

Resolve "Optionally remove identity from nodes"

Closes #8

See merge request jastadd/relast2uml!3
parents 05cf8d56 3c10ba2e
Branches
No related tags found
2 merge requests!60.3.6,!3Resolve "Optionally remove identity from nodes"
Pipeline #12724 passed
DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ; DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ;
rel DumpAst.RootNode -> DumpNode ; rel DumpAst.RootNode -> DumpNode ;
BuildConfig ::= GlobalPatternCollection:PatternCollection ExcludeTypePattern:TypePatternCollectionMapping* IncludeTypePattern:TypePatternCollectionMapping* <TypeIgnorePattern> <IncludeEmptyString:boolean> <Debug:boolean> ; BuildConfig ::= GlobalPatternCollection:PatternCollection StyleInformation ExcludeTypePattern:TypePatternCollectionMapping* IncludeTypePattern:TypePatternCollectionMapping* <TypeIgnorePattern> <IncludeEmptyString: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>;
PrintConfig ::= <Scale:double> <Version> Header* ; PrintConfig ::= <Scale:double> <Version> Header* ;
Header ::= <Value> ; Header ::= <Value> ;
DumpNode ::= <Name> <Label> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ;
DumpNode ::= <Name> <Label> <BackgroundColor> <TextColor> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ;
InnerDumpNode ; InnerDumpNode ;
rel InnerDumpNode.DumpNode -> DumpNode ; rel InnerDumpNode.DumpNode -> DumpNode ;
......
...@@ -40,101 +40,104 @@ aspect GenerationBackend { ...@@ -40,101 +40,104 @@ aspect GenerationBackend {
} else { } else {
node = new DumpNode(); node = new DumpNode();
node.setObject(obj); node.setObject(obj);
node.setLabel(objClassName + "@" + obj.hashCode());
node.setName("node" + tti.transformed.size()); node.setName("node" + tti.transformed.size());
tti.transformed.put(obj, node); tti.transformed.put(obj, node);
this.addDumpNode(node); this.addDumpNode(node);
} }
if (node.isAstNode()) { if (!node.isAstNode()) {
// do not process node further if coming from a relation return node;
if (source == Source.RELATION) { }
tti.relationTargetsUnprocessed.put(node, true); node.setLabel(getBuildConfig().getStyleInformation().getNameMethod().get(obj));
return 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
if (source == Source.RELATION) {
tti.relationTargetsUnprocessed.put(node, true);
return node;
}
if (source == Source.INVISIBLE_PARENT || !isTypeEnabled(objClassName)) {
node.setInvisible(true);
}
final ClassAnalysisResult car = analyzeClass(obj.getClass());
// -- singleChild --
for (SingleChildMethod singleChildMethod : car.singleChildMethods()) {
Object target = singleChildMethod.getMethod().invoke(obj);
String childName = singleChildMethod.getName();
DumpNode targetNode = transform(tti, target, nextSource(source, !isChildEnabled(objClassName, childName)));
if (target != null && targetNode != null) {
DumpNormalChildNode normalChild = new DumpNormalChildNode();
normalChild.setName(childName);
normalChild.setDumpNode(targetNode);
normalChild.setComputed(singleChildMethod.isNTASingleChildMethod());
node.addDumpChildNode(normalChild);
} }
if (source == Source.INVISIBLE_PARENT || !isTypeEnabled(objClassName)) { }
node.setInvisible(true); // -- listChild --
} for (ListChildMethod listChildMethod : car.listChildMethods()) {
final ClassAnalysisResult car = analyzeClass(obj.getClass()); Iterable<?> targetList = (Iterable<?>) listChildMethod.getMethod().invoke(obj);
// -- singleChild -- DumpListChildNode listChild = new DumpListChildNode();
for (SingleChildMethod singleChildMethod : car.singleChildMethods()) { listChild.setComputed(listChildMethod.isNTAListChildMethod());
Object target = singleChildMethod.getMethod().invoke(obj); String childName = listChildMethod.getName();
String childName = singleChildMethod.getName(); boolean shouldBeInvisisble = !isChildEnabled(objClassName, childName);
DumpNode targetNode = transform(tti, target, nextSource(source, !isChildEnabled(objClassName, childName))); listChild.setName(childName);
for (Object target : targetList) {
DumpNode targetNode = transform(tti, target, nextSource(source, shouldBeInvisisble));
if (target != null && targetNode != null) { if (target != null && targetNode != null) {
DumpNormalChildNode normalChild = new DumpNormalChildNode(); listChild.addInnerDumpNode(new InnerDumpNode(targetNode));
normalChild.setName(childName);
normalChild.setDumpNode(targetNode);
normalChild.setComputed(singleChildMethod.isNTASingleChildMethod());
node.addDumpChildNode(normalChild);
} }
} }
// -- listChild -- if (listChild.getNumInnerDumpNode() > 0) {
for (ListChildMethod listChildMethod : car.listChildMethods()) { node.addDumpChildNode(listChild);
Iterable<?> targetList = (Iterable<?>) listChildMethod.getMethod().invoke(obj);
DumpListChildNode listChild = new DumpListChildNode();
listChild.setComputed(listChildMethod.isNTAListChildMethod());
String childName = listChildMethod.getName();
boolean shouldBeInvisisble = !isChildEnabled(objClassName, childName);
listChild.setName(childName);
for (Object target : targetList) {
DumpNode targetNode = transform(tti, target, nextSource(source, shouldBeInvisisble));
if (target != null && targetNode != null) {
listChild.addInnerDumpNode(new InnerDumpNode(targetNode));
}
}
if (listChild.getNumInnerDumpNode() > 0) {
node.addDumpChildNode(listChild);
}
} }
// -- singleRelation -- }
for (SingleRelationMethod singleRelationMethod : car.singleRelationMethods()) { // -- singleRelation --
Object target = singleRelationMethod.getMethod().invoke(obj); for (SingleRelationMethod singleRelationMethod : car.singleRelationMethods()) {
Object target = singleRelationMethod.getMethod().invoke(obj);
DumpNode targetNode = transform(tti, target, Source.RELATION);
if (target != null && targetNode != null) {
DumpNormalRelation normalRelation = new DumpNormalRelation();
normalRelation.setName(singleRelationMethod.getName());
normalRelation.setDumpNode(targetNode);
node.addDumpRelation(normalRelation);
}
}
// -- listRelation --
for (ListRelationMethod listRelationMethod : car.listRelationMethods()) {
Iterable<?> targetList = (Iterable<?>) listRelationMethod.getMethod().invoke(obj);
DumpListRelation listRelation = new DumpListRelation();
listRelation.setName(listRelationMethod.getName());
for (Object target : targetList) {
DumpNode targetNode = transform(tti, target, Source.RELATION); DumpNode targetNode = transform(tti, target, Source.RELATION);
if (target != null && targetNode != null) { if (target != null && targetNode != null) {
DumpNormalRelation normalRelation = new DumpNormalRelation(); listRelation.addInnerDumpNode(new InnerDumpNode(targetNode));
normalRelation.setName(singleRelationMethod.getName());
normalRelation.setDumpNode(targetNode);
node.addDumpRelation(normalRelation);
} }
} }
// -- listRelation -- if (listRelation.getNumInnerDumpNode() > 0) {
for (ListRelationMethod listRelationMethod : car.listRelationMethods()) { node.addDumpRelation(listRelation);
Iterable<?> targetList = (Iterable<?>) listRelationMethod.getMethod().invoke(obj);
DumpListRelation listRelation = new DumpListRelation();
listRelation.setName(listRelationMethod.getName());
for (Object target : targetList) {
DumpNode targetNode = transform(tti, target, Source.RELATION);
if (target != null && targetNode != null) {
listRelation.addInnerDumpNode(new InnerDumpNode(targetNode));
}
}
if (listRelation.getNumInnerDumpNode() > 0) {
node.addDumpRelation(listRelation);
}
} }
// -- token -- }
for (TokenMethod tokenMethod : car.tokenMethods()) { // -- token --
Object target = tokenMethod.getMethod().invoke(obj); for (TokenMethod tokenMethod : car.tokenMethods()) {
if (target != null) { Object target = tokenMethod.getMethod().invoke(obj);
DumpNode targetNode = transform(tti, target, Source.RELATION); if (target != null) {
DumpToken token = null; DumpNode targetNode = transform(tti, target, Source.RELATION);
// TODO check, if Iterable.isAssignableFrom(target.getClass()). DumpToken token = null;
// if so, check isAstNode for first non-null to add DumpReferenceToken's, otherwise DumpValueToken's // TODO check, if Iterable.isAssignableFrom(target.getClass()).
if (targetNode != null && targetNode.isAstNode()) { // if so, check isAstNode for first non-null to add DumpReferenceToken's, otherwise DumpValueToken's
token = new DumpReferenceToken().setValue(targetNode); if (targetNode != null && targetNode.isAstNode()) {
} else { token = new DumpReferenceToken().setValue(targetNode);
if (target != null && (getBuildConfig().getIncludeEmptyString() || !target.toString().isEmpty())) { } else {
DumpValueToken valueToken = new DumpValueToken(); if (target != null && (getBuildConfig().getIncludeEmptyString() || !target.toString().isEmpty())) {
valueToken.setValue(target); DumpValueToken valueToken = new DumpValueToken();
token = valueToken; valueToken.setValue(target);
} token = valueToken;
}
if (token != null) {
token.setName(tokenMethod.getName());
token.setComputed(tokenMethod.isAttributeMethod());
node.addDumpToken(token);
} }
} }
if (token != null) {
token.setName(tokenMethod.getName());
token.setComputed(tokenMethod.isAttributeMethod());
node.addDumpToken(token);
}
} }
} }
return node; return node;
...@@ -450,6 +453,14 @@ aspect GenerationBackend { ...@@ -450,6 +453,14 @@ aspect GenerationBackend {
return result; return result;
} }
syn String DumpNode.labelAndTextColor() {
if (getTextColor().isEmpty()) {
return getLabel();
} else {
return "<color:" + getTextColor() + ">" + getLabel() + "</color>";
}
}
class TransformationTransferInformation { class TransformationTransferInformation {
java.util.Map<Object, DumpNode> transformed = new java.util.HashMap<>(); java.util.Map<Object, DumpNode> transformed = new java.util.HashMap<>();
java.util.Map<DumpNode, Boolean> relationTargetsUnprocessed = new java.util.HashMap<>(); java.util.Map<DumpNode, Boolean> relationTargetsUnprocessed = new java.util.HashMap<>();
...@@ -558,4 +569,17 @@ aspect GenerationBackend { ...@@ -558,4 +569,17 @@ aspect GenerationBackend {
public void close() { public void close() {
} }
} }
static StyleInformation StyleInformation.createDefault() {
StyleInformation result = new StyleInformation();
result.setNameMethod(n -> n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode()));
result.setBackgroundColorMethod(n -> "");
result.setTextColorMethod(n -> "");
return result;
}
@FunctionalInterface
public interface StyleMethod<ASTNODE> {
String get(ASTNODE node);
}
} }
...@@ -62,6 +62,7 @@ public class DumpBuilder { ...@@ -62,6 +62,7 @@ public class DumpBuilder {
this.target = target; this.target = target;
buildConfig = new BuildConfig(); buildConfig = new BuildConfig();
buildConfig.setGlobalPatternCollection(new PatternCollection()); buildConfig.setGlobalPatternCollection(new PatternCollection());
buildConfig.setStyleInformation(StyleInformation.createDefault());
printConfig = new PrintConfig(); printConfig = new PrintConfig();
printConfig.setScale(1); printConfig.setScale(1);
printConfig.setVersion(readVersion()); printConfig.setVersion(readVersion());
...@@ -321,6 +322,21 @@ public class DumpBuilder { ...@@ -321,6 +322,21 @@ public class DumpBuilder {
return this; return this;
} }
public <ASTNODE> DumpBuilder setNameMethod(StyleMethod<ASTNODE> nameMethod) {
buildConfig.getStyleInformation().setNameMethod(nameMethod);
return this;
}
public <ASTNODE> DumpBuilder setBackgroundColorMethod(StyleMethod<ASTNODE> colorMethod) {
buildConfig.getStyleInformation().setBackgroundColorMethod(colorMethod);
return this;
}
public <ASTNODE> DumpBuilder setTextColorMethod(StyleMethod<ASTNODE> colorMethod) {
buildConfig.getStyleInformation().setTextColorMethod(colorMethod);
return this;
}
public DumpBuilder setScale(double value) { public DumpBuilder setScale(double value) {
printConfig.setScale(value); printConfig.setScale(value);
return this; return this;
......
...@@ -9,7 +9,7 @@ scale {{Scale}} ...@@ -9,7 +9,7 @@ scale {{Scale}}
{{#DumpNodes}} {{#DumpNodes}}
{{#isAstNode}} {{#isAstNode}}
{{^Invisible}} {{^Invisible}}
object "{{label}}" as {{name}} { object "{{{labelAndTextColor}}}" as {{name}} {{#backgroundColor}}#{{{backgroundColor}}}{{/backgroundColor}} {
{{#DumpTokens}} {{#DumpTokens}}
{{#isDumpValueToken}} {{#isDumpValueToken}}
{{label}} = {{{Value}}} {{label}} = {{{Value}}}
......
...@@ -29,6 +29,9 @@ aspect GrammarGlobal { ...@@ -29,6 +29,9 @@ aspect GrammarGlobal {
syn int Root.simpleAttr() = 42; syn int Root.simpleAttr() = 42;
syn A Root.referenceAttr() = getA(); syn A Root.referenceAttr() = getA();
syn boolean ASTNode.isA() = false;
eq A.isA() = true;
} }
aspect GrammarTypeLevel { aspect GrammarTypeLevel {
......
...@@ -30,6 +30,7 @@ public class TestDumperMain { ...@@ -30,6 +30,7 @@ public class TestDumperMain {
TestUtils.ExposingDumpBuilder builder = new TestUtils.ExposingDumpBuilder(root); TestUtils.ExposingDumpBuilder builder = new TestUtils.ExposingDumpBuilder(root);
builder.includeAttributes("simpleAttr") builder.includeAttributes("simpleAttr")
.includeNonterminalAttributes("getCalculated"); .includeNonterminalAttributes("getCalculated");
builder.setNameMethod(n -> n.getClass().getSimpleName());
System.out.println(">> PlantUml"); System.out.println(">> PlantUml");
System.out.println(builder.build().toPlantUml()); System.out.println(builder.build().toPlantUml());
......
package de.tudresden.inf.st.jastadd.testDumper; package de.tudresden.inf.st.jastadd.testDumper;
import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpNode; import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpNode;
import org.jastadd.testDumper.ast.C; import org.jastadd.testDumper.ast.*;
import org.jastadd.testDumper.ast.D;
import org.jastadd.testDumper.ast.Root;
import org.jastadd.testDumper.ast.SubC;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.List; import java.util.List;
...@@ -183,4 +180,43 @@ public class TestSimple { ...@@ -183,4 +180,43 @@ public class TestSimple {
entry(TOKEN_LABEL_UNWANTED, 5)); entry(TOKEN_LABEL_UNWANTED, 5));
} }
@Test
public void testLabel() {
Root root = createRoot(createA(A_NAME), null);
List<DumpNode> nodes = TestUtils.dumpModel(root,
builder -> builder.<ASTNode<?>>setNameMethod(n -> n.isA() ? "A" : "Not A"));
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertEquals("Not A", actualRoot.getLabel());
DumpNode actualA = TestUtils.findByName(nodes, A_NAME);
assertEquals("A", actualA.getLabel());
}
@Test
public void testTextColor() {
Root root = createRoot(createA(A_NAME), null);
List<DumpNode> nodes = TestUtils.dumpModel(root,
builder -> builder.<ASTNode<?>>setTextColorMethod(n -> n.isA() ? "red" : ""));
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertEquals("", actualRoot.getTextColor());
DumpNode actualA = TestUtils.findByName(nodes, A_NAME);
assertEquals("red", actualA.getTextColor());
}
@Test
public void testBackgroundColor() {
Root root = createRoot(createA(A_NAME), null);
List<DumpNode> nodes = TestUtils.dumpModel(root,
builder -> builder.<ASTNode<?>>setBackgroundColorMethod(n -> n.isA() ? "green" : ""));
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertEquals("", actualRoot.getBackgroundColor());
DumpNode actualA = TestUtils.findByName(nodes, A_NAME);
assertEquals("green", actualA.getBackgroundColor());
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment