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

WIP: working on better visualization

- cherry-picked from 2084088d
- add method to add stereotype
- add stereotype to NTAs (probably not working)
- begin to add better options for DumpAst.transform()
parent f906bed0
No related branches found
No related tags found
1 merge request!9working on better visualization
Showing
with 449 additions and 262 deletions
...@@ -14,8 +14,10 @@ plugins { ...@@ -14,8 +14,10 @@ plugins {
apply plugin: 'jastadd' apply plugin: 'jastadd'
dependencies { dependencies {
jastadd2 "org.jastadd:jastadd:2.3.4" jastadd2 "org.jastadd:jastadd:2.3.5"
implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "${mustache_java_version}" implementation fileTree(include: ['plantuml.jar'], dir: '../libs')
implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "0.9.10"
implementation group: 'org.yaml', name: 'snakeyaml', version: '1.27'
} }
File dumpAstGrammar = file('./src/main/jastadd/DumpAst.relast') File dumpAstGrammar = file('./src/main/jastadd/DumpAst.relast')
......
DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ; DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ;
rel DumpAst.RootNode -> DumpNode ; rel DumpAst.RootNode -> DumpNode ;
BuildConfig ::= StyleInformation GlobalPatternCollection:PatternCollection
ExcludeTypePattern:TypePatternCollectionMapping* IncludeTypePattern:TypePatternCollectionMapping*
<TypeIgnorePattern> <IncludeEmptyString:boolean> <ExcludeNullNodes:boolean> <Debug:boolean>;
TypePatternCollectionMapping ::= <TypeRegex> PatternCollection ;
PatternCollection ::= <TokenPattern> <ChildPattern> <RelationPattern> <AttributePattern> <NonterminalAttributePattern> ;
StyleInformation ::= <NameMethod:StyleMethod> <BackgroundColorMethod:StyleMethod> <TextColorMethod:StyleMethod>;
PrintConfig ::= <Scale:double> <Version> <OrderChildren:boolean> Header* ;
Header ::= <Value> ;
DumpNode ::= DumpChildNode* DumpToken* DumpRelation* DumpNode ::= DumpChildNode* DumpToken* DumpRelation*
<Name> <Label> <BackgroundColor> <TextColor> <Object:Object> <Invisible:boolean> <Computed:boolean> <Name> <Label> <BackgroundColor> <TextColor> <Object:Object> <Invisible:boolean> <Computed:boolean> <ManualStereotypes>
/InvisiblePath/ ; /InvisiblePath/ ;
InnerDumpNode ; InnerDumpNode ;
rel InnerDumpNode.DumpNode <-> DumpNode.ContainerOfInner ; rel InnerDumpNode.DumpNode <-> DumpNode.ContainerOfInner ;
...@@ -52,3 +42,21 @@ ListRelationMethod : AnalysedMethod ; ...@@ -52,3 +42,21 @@ ListRelationMethod : AnalysedMethod ;
abstract TokenMethod : AnalysedMethod ; abstract TokenMethod : AnalysedMethod ;
IntrinsicTokenMethod : TokenMethod ; IntrinsicTokenMethod : TokenMethod ;
AttributeMethod : TokenMethod ; AttributeMethod : TokenMethod ;
BuildConfig ::= StyleInformation
GlobalPatternCollection:PatternCollection
ExcludeTypePattern:TypePatternCollectionMapping*
IncludeTypePattern:TypePatternCollectionMapping*
<TypeIgnorePattern>
<IncludeEmptyString:boolean>
<ExcludeNullNodes:boolean>
<Debug:boolean>;
TypePatternCollectionMapping ::= <TypeRegex> PatternCollection ;
PatternCollection ::= <TokenPattern> <ChildPattern> <RelationPattern> <AttributePattern> <NonterminalAttributePattern> ;
StyleInformation ::= <NameMethod:StyleMethod> <BackgroundColorMethod:StyleMethod> <TextColorMethod:StyleMethod> <StereotypeMethod:StyleMethod> <ComputedColor>;
PrintConfig ::= Header*
<Scale:double>
<Version>
<OrderChildren:boolean> ;
Header ::= <Value> ;
...@@ -5,6 +5,53 @@ aspect GenerationBackend { ...@@ -5,6 +5,53 @@ aspect GenerationBackend {
} }
} }
class TransformationOptions {
// todo should be read-only, i.e., copy-on-write
public boolean relation = false;
public boolean invisible = false;
public boolean root = false;
public boolean allowNullObject = false;
public boolean computed = false;
public static TransformationOptions with() {
return new TransformationOptions();
}
public TransformationOptions relationTrue() {
TransformationOptions copy = new TransformationOptions(this);
copy.relation = true;
return copy;
}
public TransformationOptions invisibleTrue() {
TransformationOptions copy = new TransformationOptions(this);
copy.invisible = true;
return copy;
}
public TransformationOptions rootTrue() {
TransformationOptions copy = new TransformationOptions(this);
copy.root = true;
return copy;
}
public TransformationOptions allowNullObjectTrue() {
TransformationOptions copy = new TransformationOptions(this);
copy.allowNullObject = true;
return copy;
}
public TransformationOptions computedTrue() {
TransformationOptions copy = new TransformationOptions(this);
copy.computed = true;
return copy;
}
protected TransformationOptions() {}
protected TransformationOptions(TransformationOptions prototype) {
this.relation = prototype.relation;
this.invisible = prototype.invisible;
this.root = prototype.root;
this.allowNullObject = prototype.allowNullObject;
this.computed = prototype.computed;
}
}
// --- transform --- (need to be a method, because it alters the AST while traversing the object structure) // --- transform --- (need to be a method, because it alters the AST while traversing the object structure)
protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj) protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj)
throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException { throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
...@@ -196,6 +243,7 @@ aspect GenerationBackend { ...@@ -196,6 +243,7 @@ aspect GenerationBackend {
node.setLabel(getBuildConfig().getStyleInformation().getNameMethod().get(obj)); node.setLabel(getBuildConfig().getStyleInformation().getNameMethod().get(obj));
node.setBackgroundColor(getBuildConfig().getStyleInformation().getBackgroundColorMethod().get(obj)); node.setBackgroundColor(getBuildConfig().getStyleInformation().getBackgroundColorMethod().get(obj));
node.setTextColor(getBuildConfig().getStyleInformation().getTextColorMethod().get(obj)); node.setTextColor(getBuildConfig().getStyleInformation().getTextColorMethod().get(obj));
node.setManualStereotypes(getBuildConfig().getStyleInformation().getStereotypeMethod().get(obj));
} }
private Source DumpAst.nextSource(Source currentSource, boolean shouldBeInvisible) { private Source DumpAst.nextSource(Source currentSource, boolean shouldBeInvisible) {
...@@ -491,8 +539,8 @@ aspect GenerationBackend { ...@@ -491,8 +539,8 @@ aspect GenerationBackend {
return p.matcher(input).matches(); return p.matcher(input).matches();
} }
// --- version --- (mustache has buildConfig as context) // --- debug --- (mustache has printConfig as context)
syn String BuildConfig.version() = printConfig().getVersion(); syn boolean PrintConfig.debug() = buildConfig().getDebug();
private static String DumpAst.invokeName(java.lang.annotation.Annotation annotation) { private static String DumpAst.invokeName(java.lang.annotation.Annotation annotation) {
return (String) invokeMethod("name", annotation); return (String) invokeMethod("name", annotation);
...@@ -567,6 +615,30 @@ aspect GenerationBackend { ...@@ -567,6 +615,30 @@ aspect GenerationBackend {
} }
} }
// --- 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 --- // --- 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<>();
...@@ -602,94 +674,19 @@ aspect GenerationBackend { ...@@ -602,94 +674,19 @@ aspect GenerationBackend {
int nodeCounter = 0; int nodeCounter = 0;
} }
syn String DumpAst.toYaml(boolean prependCreationComment) {
Document doc = new Document();
doc.setRootElement(getRootNode().toYaml());
return doc.prettyPrint(prependCreationComment);
}
syn MappingElement DumpNode.toYaml() {
MappingElement result = new MappingElement();
// tokens are key-value-pairs
for (DumpToken token : getDumpTokenList()) {
if (token.isDumpValueToken()) {
result.put(token.getName(), makeValueElement(token.asDumpValueToken().getValue()));
} else {
result.put(token.getName(), token.asDumpReferenceToken().getValue().toYaml());
}
}
// children
for (DumpChildNode child : getDumpChildNodeList()) {
ListElement list = new ListElement();
for (DumpNode inner : child.innerNodes(true)) {
list.add(inner.toYaml());
}
if (child.isList()) {
result.put(child.getName(), list);
} else if (list.getNumElement() == 1) {
result.put(child.getName(), list.getElement(0));
}
}
// relations
for (DumpRelation relation : getDumpRelationList()) {
ListElement list = new ListElement();
for (DumpNode inner : relation.innerNodes(true)) {
list.add(inner.toYaml());
}
if (relation.isList()) {
result.put(relation.getName(), list);
} else if (list.getNumElement() == 1) {
result.put(relation.getName(), list.getElement(0));
}
}
return result;
}
private static ComplexElement ASTNode.HELPER_COMPLEX_ELEMENT = new MappingElement();
protected static Element ASTNode.makeValueElement(Object obj) {
if (obj instanceof Integer) {
return ValueElement.of((int) obj);
} else if (obj instanceof Boolean) {
return ValueElement.of((boolean) obj);
} else {
return HELPER_COMPLEX_ELEMENT.makeStringElement(obj.toString());
}
}
public class AppendableWriter extends java.io.Writer {
private final StringBuilder sb;
public AppendableWriter(StringBuilder sb) {
this.sb = sb;
}
@Override
public void write(char[] chars, int off, int len) {
sb.append(chars, off, len);
}
@Override
public void write(String str) {
sb.append(str);
}
@Override
public void flush() {
}
@Override
public void close() {
}
}
static StyleInformation StyleInformation.createDefault() { static StyleInformation StyleInformation.createDefault() {
StyleInformation result = new StyleInformation(); StyleInformation result = new StyleInformation();
result.setNameMethod(n -> n == null ? "null" : 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 -> "");
result.setStereotypeMethod(n -> "");
result.setComputedColor("blue");
return result; return result;
} }
syn String DumpAst.computedColor() = getBuildConfig().getStyleInformation().getComputedColor();
@FunctionalInterface @FunctionalInterface
public interface StyleMethod<ASTNODE> { public interface StyleMethod<ASTNODE> {
String get(ASTNODE node); String get(ASTNODE node);
......
...@@ -347,6 +347,16 @@ public class DumpBuilder { ...@@ -347,6 +347,16 @@ public class DumpBuilder {
return this; return this;
} }
public <ASTNODE> DumpBuilder setStereotypeMethod(StyleMethod<ASTNODE> stereotypeMethod) {
buildConfig.getStyleInformation().setStereotypeMethod(stereotypeMethod);
return this;
}
public DumpBuilder setComputedColor(String color) {
buildConfig.getStyleInformation().setComputedColor(color);
return this;
}
public DumpBuilder setScale(double value) { public DumpBuilder setScale(double value) {
printConfig.setScale(value); printConfig.setScale(value);
return this; return this;
...@@ -400,11 +410,38 @@ public class DumpBuilder { ...@@ -400,11 +410,38 @@ public class DumpBuilder {
} }
public DumpBuilder dumpAsYaml(java.nio.file.Path destination, boolean prependCreationComment) throws java.io.IOException { public DumpBuilder dumpAsYaml(java.nio.file.Path destination, boolean prependCreationComment) throws java.io.IOException {
String content = build().toYaml(prependCreationComment); String content = build().printYaml(prependCreationComment);
try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) { try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
writer.write(content); writer.write(content);
} }
return this; return this;
} }
/**
* Write out content as PNG image generated by plantuml.
* @param destination path of destination file
* @return this
* @throws java.io.IOException if an I/O error happend during opening or writing in that file
*/
public DumpBuilder dumpAsPNG(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
net.sourceforge.plantuml.SourceStringReader reader = new net.sourceforge.plantuml.SourceStringReader(content);
reader.outputImage(java.nio.file.Files.newOutputStream(destination));
return this;
}
/**
* Write out content as SVG image generated by plantuml.
* @param destination path of destination file
* @return this
* @throws java.io.IOException if an I/O error happend during opening or writing in that file
*/
public DumpBuilder dumpAsSVG(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
net.sourceforge.plantuml.SourceStringReader reader = new net.sourceforge.plantuml.SourceStringReader(content);
reader.outputImage(java.nio.file.Files.newOutputStream(destination),
new net.sourceforge.plantuml.FileFormatOption(net.sourceforge.plantuml.FileFormat.SVG));
return this;
}
} }
} }
...@@ -19,7 +19,35 @@ aspect GenerationMustache { ...@@ -19,7 +19,35 @@ aspect GenerationMustache {
com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory(); com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory();
mf.setObjectHandler(roh); mf.setObjectHandler(roh);
com.github.mustachejava.Mustache m = mf.compile("dumpAst.mustache"); com.github.mustachejava.Mustache m = mf.compile("dumpAst.mustache");
m.execute(new java.io.PrintWriter(new AppendableWriter(sb)), this); String yaml = this.printYaml(false);
Object context = new org.yaml.snakeyaml.Yaml().load(new StringReader(yaml));
m.execute(new java.io.PrintWriter(new AppendableWriter(sb)), context);
return sb.toString(); return sb.toString();
} }
public class AppendableWriter extends java.io.Writer {
private final StringBuilder sb;
public AppendableWriter(StringBuilder sb) {
this.sb = sb;
}
@Override
public void write(char[] chars, int off, int len) {
sb.append(chars, off, len);
}
@Override
public void write(String str) {
sb.append(str);
}
@Override
public void flush() {
}
@Override
public void close() {
}
}
} }
aspect GenerationToYaml {
syn String DumpAst.printYaml(boolean prependCreationComment) {
Document doc = new Document();
doc.setRootElement(this.toYaml(false));
return doc.prettyPrint(prependCreationComment);
}
// todo: default impl should actually be abstract instead
syn MappingElement ASTNode.toYaml(boolean fromRelation) = new MappingElement();
static MappingElement ASTNode.safeToYaml(ASTNode node, boolean fromRelation) {
if (node == null) {
return null;
}
return node.toYaml(fromRelation);
}
syn MappingElement DumpAst.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// children
result.put("PrintConfig", safeToYaml(getPrintConfig(), fromRelation));
addYamledList(result, "DumpNodes", getDumpNodeList(), fromRelation);
// attributes
result.put("computedColor", computedColor());
return result;
}
static void ASTNode.addYamledList(MappingElement base, String key, Iterable<? extends ASTNode<?>> iterable, boolean fromRelation) {
ListElement innerList = new ListElement();
for (ASTNode node : iterable) {
innerList.add(safeToYaml(node, fromRelation));
}
base.put(key, innerList);
}
syn MappingElement PrintConfig.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// children
addYamledList(result, "Headers", getHeaderList(), fromRelation);
// tokens
result.put("scale", getScale());
result.put("version", getVersion());
result.put("orderChildren", getOrderChildren());
// attributes
result.put("debug", debug());
return result;
}
syn MappingElement Header.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// tokens
result.put("value", getValue());
return result;
}
syn MappingElement DumpNode.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// children
if (!fromRelation) {
addYamledList(result, "DumpChildNodes", getDumpChildNodeList(), fromRelation);
addYamledList(result, "DumpTokens", getDumpTokenList(), fromRelation);
addYamledList(result, "DumpRelations", getDumpRelationList(), fromRelation);
}
// tokens
result.put("name", getName());
if (!fromRelation) {
result.put("computed", getComputed());
result.put("label", getLabel());
result.put("backgroundColor", getBackgroundColor());
result.put("textColor", getTextColor());
result.put("invisible", getInvisible());
}
// attributes
if (!fromRelation) {
result.put("isNull", isNull());
result.put("isAstNode", isAstNode());
result.put("labelAndTextColor", labelAndTextColor());
result.put("stereotypeList", stereotypeList());
addYamledList(result, "myChildren", myChildren(), true);
}
result.put("hasSuccessor", hasSuccessor());
result.put("successor", safeToYaml(successor(), true));
// NTAs
if (!fromRelation) {
result.put("InvisiblePath", safeToYaml(getInvisiblePath(), true));
}
return result;
}
syn MappingElement DumpChildNode.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// tokens
result.put("name", getName());
result.put("computed", getComputed());
// attributes
result.put("label", label());
result.put("isList", isList());
result.put("outerNodeName", outerNodeName());
return result;
}
syn MappingElement DumpNormalChildNode.toYaml(boolean fromRelation) {
MappingElement result = super.toYaml(fromRelation);
// attributes
result.put("bothVisible", bothVisible());
result.put("innerNodeName", innerNodeName());
return result;
}
syn MappingElement DumpListChildNode.toYaml(boolean fromRelation) {
MappingElement result = super.toYaml(fromRelation);
// children
addYamledList(result, "InnerDumpNodes", getInnerDumpNodeList(), fromRelation);
return result;
}
syn MappingElement DumpToken.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// tokens
result.put("name", getName());
result.put("computed", getComputed());
// attributes
result.put("label", label());
result.put("isDumpValueToken", isDumpValueToken());
return result;
}
syn MappingElement DumpValueToken.toYaml(boolean fromRelation) {
MappingElement result = super.toYaml(fromRelation);
// tokens
result.put("value", getValue().toString());
return result;
}
syn MappingElement DumpReferenceToken.toYaml(boolean fromRelation) {
MappingElement result = super.toYaml(fromRelation);
// tokens
result.put("innerNodeName", innerNodeName());
result.put("outerNodeName", outerNodeName());
return result;
}
syn MappingElement DumpRelation.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// tokens
result.put("name", getName());
result.put("bidirectional", getBidirectional());
// attributes
result.put("isList", isList());
result.put("label", label());
result.put("outerNodeName", outerNodeName());
return result;
}
syn MappingElement DumpNormalRelation.toYaml(boolean fromRelation) {
MappingElement result = super.toYaml(fromRelation);
// attributes
result.put("bothVisible", bothVisible());
result.put("innerNodeName", innerNodeName());
return result;
}
syn MappingElement DumpListRelation.toYaml(boolean fromRelation) {
MappingElement result = super.toYaml(fromRelation);
// children
addYamledList(result, "InnerDumpNodes", getInnerDumpNodeList(), fromRelation);
return result;
}
syn MappingElement InnerDumpNode.toYaml(boolean fromRelation) {
MappingElement result = new MappingElement();
// attributes
result.put("bothVisible", bothVisible());
result.put("innerNodeName", innerNodeName());
result.put("outerNodeName", outerNodeName());
result.put("label", label());
return result;
}
syn MappingElement InvisiblePath.toYaml(boolean fromRelation) {
MappingElement result = super.toYaml(fromRelation);
// children
addYamledList(result, "InnerDumpNodes", getInnerDumpNodeList(), fromRelation);
return result;
}
// extension for mustache
public static ValueElement ValueElement.of(double value) {
return new ValueElement(false, String.valueOf(value));
}
public MappingElement MappingElement.put(String key, double value) {
addKeyValuePair(key, ValueElement.of(value));
return this;
}
refine Helpers public void MappingElement.addKeyValuePair(String key, Element value) {
if (value == null) {
return;
}
refined(key, value);
}
refine Helpers protected SimpleElement ComplexElement.makeStringElement(String value) {
if (value == null || value.equals("null")) {
return StringElement.of("null");
}
if (value.isEmpty()) {
return StringElement.of(value);
}
return refined(value);
}
}
import java.io.*;
import java.util.*;
aspect Imports {}
...@@ -7,6 +7,7 @@ aspect Navigation { ...@@ -7,6 +7,7 @@ aspect Navigation {
// --- buildConfig --- // --- buildConfig ---
inh BuildConfig DumpNode.buildConfig(); inh BuildConfig DumpNode.buildConfig();
inh BuildConfig PrintConfig.buildConfig();
eq DumpAst.getChild().buildConfig() = getBuildConfig(); eq DumpAst.getChild().buildConfig() = getBuildConfig();
// --- printConfig --- // --- printConfig ---
...@@ -38,7 +39,7 @@ aspect Navigation { ...@@ -38,7 +39,7 @@ aspect Navigation {
// --- innerNodes --- // --- innerNodes ---
syn java.util.List<DumpNode> DumpChildNode.innerNodes(boolean onlyVisible); syn java.util.List<DumpNode> DumpChildNode.innerNodes(boolean onlyVisible);
eq DumpNormalChildNode.innerNodes(boolean onlyVisible) = onlyVisible && (containingDumpNode().getInvisible() || getDumpNode().getInvisible()) ? eq DumpNormalChildNode.innerNodes(boolean onlyVisible) = getDumpNode() == null || onlyVisible && (containingDumpNode().getInvisible() || getDumpNode().getInvisible()) ?
java.util.Collections.emptyList() : java.util.Collections.emptyList() :
java.util.Collections.singletonList(getDumpNode()); java.util.Collections.singletonList(getDumpNode());
eq DumpListChildNode.innerNodes(boolean onlyVisible) { eq DumpListChildNode.innerNodes(boolean onlyVisible) {
...@@ -47,9 +48,15 @@ aspect Navigation { ...@@ -47,9 +48,15 @@ aspect Navigation {
} }
java.util.List<DumpNode> result = new java.util.ArrayList<>(); java.util.List<DumpNode> result = new java.util.ArrayList<>();
getInnerDumpNodeList().forEach(inner -> { getInnerDumpNodeList().forEach(inner -> {
if (!onlyVisible || !inner.getDumpNode().getInvisible()) { if (inner == null || inner.getDumpNode() == null) {
result.add(inner.getDumpNode()); //noinspection UnnecessaryReturnStatement
return;
} }
if (onlyVisible && inner.getDumpNode().getInvisible()) {
//noinspection UnnecessaryReturnStatement
return;
}
result.add(inner.getDumpNode());
}); });
return result; return result;
} }
......
...@@ -7,9 +7,9 @@ aspect Printing { ...@@ -7,9 +7,9 @@ aspect Printing {
eq DumpNode.getChild().outerNodeName() = name(); eq DumpNode.getChild().outerNodeName() = name();
// --- innerNodeName --- // --- innerNodeName ---
syn String InnerDumpNode.innerNodeName() = getDumpNode().name(); syn String InnerDumpNode.innerNodeName() = getDumpNode() != null ? getDumpNode().name() : null;
syn String DumpNormalChildNode.innerNodeName() = getDumpNode().name(); syn String DumpNormalChildNode.innerNodeName() = getDumpNode() != null ? getDumpNode().name() : null;
syn String DumpNormalRelation.innerNodeName() = getDumpNode().name(); syn String DumpNormalRelation.innerNodeName() = getDumpNode() != null ? getDumpNode().name() : null;
syn String DumpReferenceToken.innerNodeName() = getValue().name(); syn String DumpReferenceToken.innerNodeName() = getValue().name();
// --- name --- // --- name ---
...@@ -20,6 +20,10 @@ aspect Printing { ...@@ -20,6 +20,10 @@ aspect Printing {
syn String DumpRelation.label() = getName(); syn String DumpRelation.label() = getName();
syn String DumpToken.label() = getName() + (getComputed() ? "()" : ""); syn String DumpToken.label() = getName() + (getComputed() ? "()" : "");
syn String DumpNode.label() = getLabel(); syn String DumpNode.label() = getLabel();
inh String InnerDumpNode.label();
eq DumpListChildNode.getInnerDumpNode(int index).label() = label() + "[" + index + "]";
eq DumpListRelation.getInnerDumpNode(int index).label() = label() + "[" + index + "]";
eq InvisiblePath.getInnerDumpNode(int index).label() = null;
// --- bothVisible --- // --- bothVisible ---
boolean ASTNode.bothVisible(DumpNode one, DumpNode two) { boolean ASTNode.bothVisible(DumpNode one, DumpNode two) {
......
@startuml @startuml
skinparam object<<null>> {
BorderColor transparent
BackgroundColor transparent
shadowing false
}
hide <<null>> stereotype
{{#PrintConfig}} {{#PrintConfig}}
scale {{{Scale}}} scale {{{scale}}}
{{#Headers}} {{#Headers}}
{{{Value}}} {{{value}}}
{{/Headers}} {{/Headers}}
{{/PrintConfig}} {{/PrintConfig}}
{{#DumpNodes}} {{#DumpNodes}}
{{^Invisible}} {{^invisible}}
{{#isNull}} {{#isNull}}
diamond {{{name}}} object "null" as {{{name}}}<<null>>
{{/isNull}} {{/isNull}}
{{#isAstNode}} {{#isAstNode}}
object "{{{labelAndTextColor}}}" as {{{name}}} {{#backgroundColor}}#{{{backgroundColor}}}{{/backgroundColor}} { object "{{{labelAndTextColor}}}" as {{{name}}} {{{stereotypeList}}} {{#backgroundColor}}#{{{backgroundColor}}}{{/backgroundColor}} {
{{#DumpTokens}} {{#DumpTokens}}
{{#isDumpValueToken}} {{#isDumpValueToken}}
{{{label}}} = {{{Value}}} {{{label}}} = {{{value}}}
{{/isDumpValueToken}} {{/isDumpValueToken}}
{{/DumpTokens}} {{/DumpTokens}}
} }
{{/isAstNode}} {{/isAstNode}}
{{/Invisible}} {{/invisible}}
{{/DumpNodes}} {{/DumpNodes}}
{{#DumpNodes}} {{#DumpNodes}}
{{#DumpTokens}} {{#DumpTokens}}
{{^Invisible}} {{^invisible}}
{{^isDumpValueToken}} {{^isDumpValueToken}}
{{{outerNodeName}}} .{{#Computed}}[#blue]{{/Computed}}.> {{{innerNodeName}}} : {{{label}}} {{{outerNodeName}}} .{{#computed}}[#{{{computedColor}}}]{{/computed}}.> {{{innerNodeName}}} : {{{label}}}
{{/isDumpValueToken}} {{/isDumpValueToken}}
{{/Invisible}} {{/invisible}}
{{/DumpTokens}} {{/DumpTokens}}
{{#DumpChildNodes}} {{#DumpChildNodes}}
{{#isList}} {{#isList}}
{{#InnerDumpNodes}} {{#InnerDumpNodes}}
{{#bothVisible}} {{#bothVisible}}
{{{outerNodeName}}} *-{{#Computed}}[#blue]{{/Computed}}- {{{innerNodeName}}} : {{{label}}} {{{outerNodeName}}} *-{{#computed}}[#{{{computedColor}}}]{{/computed}}- {{{innerNodeName}}} : {{{label}}}
{{/bothVisible}} {{/bothVisible}}
{{/InnerDumpNodes}} {{/InnerDumpNodes}}
{{/isList}} {{/isList}}
{{^isList}} {{^isList}}
{{#bothVisible}} {{#bothVisible}}
{{{outerNodeName}}} *-{{#Computed}}[#blue]{{/Computed}}- {{{innerNodeName}}} : {{{label}}} {{{outerNodeName}}} *-{{#computed}}[#{{{computedColor}}}]{{/computed}}- {{{innerNodeName}}} : {{{label}}}
{{/bothVisible}} {{/bothVisible}}
{{/isList}} {{/isList}}
{{/DumpChildNodes}} {{/DumpChildNodes}}
...@@ -49,23 +56,23 @@ object "{{{labelAndTextColor}}}" as {{{name}}} {{#backgroundColor}}#{{{backgroun ...@@ -49,23 +56,23 @@ object "{{{labelAndTextColor}}}" as {{{name}}} {{#backgroundColor}}#{{{backgroun
{{#isList}} {{#isList}}
{{#InnerDumpNodes}} {{#InnerDumpNodes}}
{{#bothVisible}} {{#bothVisible}}
{{{outerNodeName}}} {{#Bidirectional}}<{{/Bidirectional}}--> {{{innerNodeName}}} : {{{label}}} {{{outerNodeName}}} {{#bidirectional}}<{{/bidirectional}}--> {{{innerNodeName}}} : {{{label}}}
{{/bothVisible}} {{/bothVisible}}
{{/InnerDumpNodes}} {{/InnerDumpNodes}}
{{/isList}} {{/isList}}
{{^isList}} {{^isList}}
{{#bothVisible}} {{#bothVisible}}
{{{outerNodeName}}} {{#Bidirectional}}<{{/Bidirectional}}--> {{{innerNodeName}}} : {{{label}}} {{{outerNodeName}}} {{#bidirectional}}<{{/bidirectional}}--> {{{innerNodeName}}} : {{{label}}}
{{/bothVisible}} {{/bothVisible}}
{{/isList}} {{/isList}}
{{/DumpRelations}} {{/DumpRelations}}
{{^Invisible}} {{^invisible}}
{{#InvisiblePath}} {{#InvisiblePath}}
{{#InnerDumpNodes}} {{#InnerDumpNodes}}
{{{outerNodeName}}} o.. {{{innerNodeName}}} {{{outerNodeName}}} o.. {{{innerNodeName}}}
{{/InnerDumpNodes}} {{/InnerDumpNodes}}
{{/InvisiblePath}} {{/InvisiblePath}}
{{/Invisible}} {{/invisible}}
{{#PrintConfig}}{{#orderChildren}} {{#PrintConfig}}{{#orderChildren}}
{{#myChildren}} {{#myChildren}}
{{#hasSuccessor}} {{#hasSuccessor}}
...@@ -74,13 +81,13 @@ object "{{{labelAndTextColor}}}" as {{{name}}} {{#backgroundColor}}#{{{backgroun ...@@ -74,13 +81,13 @@ object "{{{labelAndTextColor}}}" as {{{name}}} {{#backgroundColor}}#{{{backgroun
{{/myChildren}} {{/myChildren}}
{{/orderChildren}}{{/PrintConfig}} {{/orderChildren}}{{/PrintConfig}}
{{/DumpNodes}} {{/DumpNodes}}
{{#BuildConfig}} {{#PrintConfig}}
{{#Debug}} {{#debug}}
legend right legend right
%date() %date()
dumpAst: {{{version}}} dumpAst: {{{version}}}
plantuml: %version() plantuml: %version()
endlegend endlegend
{{/Debug}} {{/debug}}
{{/BuildConfig}} {{/PrintConfig}}
@enduml @enduml
#Thu Feb 24 09:45:15 CET 2022 #Wed Mar 02 15:04:33 CET 2022
version=0.3.6 version=0.3.7
build
src/gen-res/
src/gen/
out/
*.class
buildscript {
repositories.mavenLocal()
repositories.mavenCentral()
dependencies {
classpath group: 'org.jastadd', name: 'jastaddgradle', version: '1.13.3'
}
}
plugins {
id 'relast2uml.java-jastadd-conventions'
id 'relast2uml.java-publishing-conventions'
}
apply plugin: 'jastadd'
dependencies {
implementation fileTree(include: ['plantuml.jar'], dir: '../libs')
implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "${mustache_java_version}"
}
File dumpAstGrammar = file('../dumpAst/src/main/jastadd/DumpAst.relast')
task relast(type: JavaExec) {
group = 'Build'
main = "-jar"
doFirst {
delete "src/gen/jastadd/*.ast"
delete "src/gen/jastadd/DumpAst.jadd"
delete "src/gen/jastadd/DumpAstRefResolver.jadd"
delete "src/gen/jastadd/DumpAstResolverStubs.jrag"
mkdir "src/gen/jastadd/"
}
args = [
"../libs/relast.jar",
dumpAstGrammar,
// "./src/main/jastadd/MustacheNodes.relast",
"--listClass=java.util.ArrayList",
"--jastAddList=JastAddList",
"--useJastAddNames",
"--file",
"--resolverHelper",
"--grammarName=./src/gen/jastadd/DumpAst"
]
inputs.files(file("../libs/relast.jar"),
dumpAstGrammar)
outputs.files(file("./src/gen/jastadd/DumpAst.ast"),
file("./src/gen/jastadd/DumpAst.jadd"),
file("./src/gen/jastadd/DumpAstRefResolver.jadd"),
file('./src/gen/jastadd/DumpAstResolverStubs.jrag'))
}
jastadd {
configureModuleBuild()
modules {
//noinspection GroovyAssignabilityCheck
module("DumpAstWithPlantuml") {
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 "dumpAstWithPlantuml/src/main/jastadd/**/*.jadd"
include "dumpAst/src/gen/jastadd/**/*.ast"
include "dumpAst/src/gen/jastadd/**/*.jadd"
include "dumpAst/src/gen/jastadd/**/*.jrag"
}
}
}
cleanGen.doFirst {
delete "src/gen/java/de"
delete "src/gen-res/BuildInfo.properties"
}
preprocessParser.doFirst {
args += ["--no-beaver-symbol"]
}
module = "DumpAstWithPlantuml"
astPackage = 'de.tudresden.inf.st.jastadd.dumpAst.ast'
genDir = 'src/gen/java'
buildInfoDir = 'src/gen-res'
jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
}
generateAst.dependsOn relast
aspect Generation {
/**
* Write out content as PNG image generated by plantuml.
* @param destination path of destination file
* @return this
* @throws java.io.IOException if an I/O error happend during opening or writing in that file
*/
public DumpBuilder DumpBuilder.dumpAsPNG(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
net.sourceforge.plantuml.SourceStringReader reader = new net.sourceforge.plantuml.SourceStringReader(content);
reader.outputImage(java.nio.file.Files.newOutputStream(destination));
return this;
}
/**
* Write out content as SVG image generated by plantuml.
* @param destination path of destination file
* @return this
* @throws java.io.IOException if an I/O error happend during opening or writing in that file
*/
public DumpBuilder DumpBuilder.dumpAsSVG(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
net.sourceforge.plantuml.SourceStringReader reader = new net.sourceforge.plantuml.SourceStringReader(content);
reader.outputImage(java.nio.file.Files.newOutputStream(destination),
new net.sourceforge.plantuml.FileFormatOption(net.sourceforge.plantuml.FileFormat.SVG));
return this;
}
}
\ No newline at end of file
../../../../dumpAst/src/main/resources/dumpAst.mustache
\ No newline at end of file
../../../../dumpAst/src/main/resources/dumpAstVersion.properties
\ No newline at end of file
...@@ -19,7 +19,7 @@ repositories { ...@@ -19,7 +19,7 @@ repositories {
mainClassName = 'de.tudresden.inf.st.jastadd.featureTest.FeatureTestMain' mainClassName = 'de.tudresden.inf.st.jastadd.featureTest.FeatureTestMain'
dependencies { dependencies {
implementation project(":dumpAstWithPlantuml") implementation project(":dumpAst")
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
......
...@@ -51,4 +51,9 @@ public class FeatureTestMain { ...@@ -51,4 +51,9 @@ public class FeatureTestMain {
.dumpAsYaml(pathToYaml, true) .dumpAsYaml(pathToYaml, true)
.dumpAsPNG(pathToPng); .dumpAsPNG(pathToPng);
} }
private void m() {
//noinspection UnnecessaryReturnStatement
return;
}
} }
...@@ -2,7 +2,6 @@ rootProject.name = 'relast2uml' ...@@ -2,7 +2,6 @@ rootProject.name = 'relast2uml'
include 'relast.preprocessor' include 'relast.preprocessor'
include 'dumpAst' include 'dumpAst'
include 'dumpAstWithPlantuml'
include 'testDumper' include 'testDumper'
include 'featureTest' include 'featureTest'
...@@ -8,14 +8,17 @@ buildscript { ...@@ -8,14 +8,17 @@ buildscript {
plugins { plugins {
id 'relast2uml.java-jastadd-conventions' id 'relast2uml.java-jastadd-conventions'
id 'relast2uml.java-application-conventions'
} }
apply plugin: 'jastadd' apply plugin: 'jastadd'
dependencies { dependencies {
testImplementation project(':dumpAst') implementation project(':dumpAst')
} }
mainClassName = 'de.tudresden.inf.st.jastadd.testDumper.TestDumperMain'
File testingGrammar = file('./src/main/jastadd/testDumper.relast') File testingGrammar = file('./src/main/jastadd/testDumper.relast')
task relast(type: JavaExec) { task relast(type: JavaExec) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment