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
This commit is part of merge request !9. Comments created here will be created in the context of that merge request.
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