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

Merge branch 'release-1.0.0' into 'master'

1.0.0

See merge request jastadd/relast2uml!10
parents ec2ab792 fb67ef02
No related branches found
No related tags found
1 merge request!101.0.0
Pipeline #12961 passed
Showing
with 969 additions and 423 deletions
...@@ -45,6 +45,7 @@ publish_master: ...@@ -45,6 +45,7 @@ publish_master:
script: script:
- "./gradlew publish" - "./gradlew publish"
only: only:
- main
- master - master
ragdoc_build: ragdoc_build:
...@@ -55,7 +56,7 @@ ragdoc_build: ...@@ -55,7 +56,7 @@ ragdoc_build:
needs: needs:
- build - build
script: script:
- JAVA_FILES=$(find dumpAstWithPlantuml/src/ -name '*.java') - JAVA_FILES=$(find dumpAst/src/ -name '*.java')
- /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES - /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES
artifacts: artifacts:
paths: paths:
...@@ -77,6 +78,7 @@ ragdoc_view: ...@@ -77,6 +78,7 @@ ragdoc_view:
only: only:
- dev - dev
- main - main
- master
artifacts: artifacts:
paths: paths:
- "pages/docs/ragdoc" - "pages/docs/ragdoc"
...@@ -96,3 +98,4 @@ pages: ...@@ -96,3 +98,4 @@ pages:
- public/ - public/
only: only:
- main - main
- master
# DumpAst
For documentation, please see https://jastadd.pages.st.inf.tu-dresden.de/relast2uml/
plugins {
id 'relast2uml.java-common-conventions'
id 'application'
}
plugins {
id 'java'
id 'idea'
id 'com.github.ben-manes.versions'
}
repositories {
mavenCentral()
}
dependencies {
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: "${jupiter_version}"
testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1'
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: "${jupiter_version}"
}
tasks.named('test') {
useJUnitPlatform()
}
plugins {
id 'relast2uml.java-common-conventions'
id 'java-library'
}
dependencies {
api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
}
File genSrc = file("src/gen/java")
sourceSets.main.java.srcDir genSrc
idea.module.generatedSourceDirs += genSrc
plugins {
id 'java'
id 'idea'
id 'com.github.ben-manes.versions'
id 'maven-publish'
}
repositories {
mavenCentral()
}
dependencies {
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: "${jupiter_version}"
testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.18.1'
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: "${jupiter_version}"
}
jar {
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
def versionFile = "src/main/resources/${project.getName()}Version.properties"
def oldProps = new Properties()
try {
file(versionFile).withInputStream { stream -> oldProps.load(stream) }
version = oldProps['version']
} catch (e) {
// this happens, if either the properties file is not present, or cannot be read from
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.", e)
}
task printVersion() {
doLast {
println(version)
}
}
task newVersion() {
doFirst {
def props = new Properties()
props['version'] = value
props.store(file(versionFile).newWriter(), null)
}
}
task setDevVersionForCI() {
doFirst {
def props = new Properties()
props['version'] = version + "-$System.env.CI_PIPELINE_IID"
props.store(file(versionFile).newWriter(), null)
}
}
//679
publishing {
publications {
maven(MavenPublication) {
groupId = 'de.tudresden.inf.st'
// from components.java
artifact("build/libs/${project.getName()}-${project.getVersion()}.jar") {
extension 'jar'
}
}
}
repositories {
maven {
url "https://git-st.inf.tu-dresden.de/api/v4/projects/679/packages/maven"
// Uncomment the following lines to publish manually (and comment out the other credentials section)
// credentials(HttpHeaderCredentials) {
// name = "Private-Token"
// value = gitLabPrivateToken // the variable resides in ~/.gradle/gradle.properties
// }
credentials(HttpHeaderCredentials) {
name = 'Job-Token'
value = System.getenv("CI_JOB_TOKEN")
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}
publish.dependsOn jar
// --- Buildscripts (must be at the top) ---
buildscript { buildscript {
repositories.mavenLocal() repositories.mavenLocal()
repositories.mavenCentral() repositories.mavenCentral()
...@@ -6,18 +7,35 @@ buildscript { ...@@ -6,18 +7,35 @@ buildscript {
} }
} }
// --- Plugin definitions ---
plugins { plugins {
id 'relast2uml.java-jastadd-conventions' id 'java'
id 'relast2uml.java-publishing-conventions' id 'idea'
id 'com.github.ben-manes.versions'
id 'java-library'
id 'maven-publish'
} }
apply plugin: 'jastadd' apply plugin: 'jastadd'
// --- Dependencies ---
repositories {
mavenCentral()
}
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')
api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "0.9.10"
implementation group: 'org.yaml', name: 'snakeyaml', version: '1.27'
} }
// --- Preprocessors ---
File genSrc = file("src/gen/java")
sourceSets.main.java.srcDir genSrc
idea.module.generatedSourceDirs += genSrc
File dumpAstGrammar = file('./src/main/jastadd/DumpAst.relast') File dumpAstGrammar = file('./src/main/jastadd/DumpAst.relast')
File mustacheGrammar = file('./src/main/jastadd/mustache/Mustache.relast') File mustacheGrammar = file('./src/main/jastadd/mustache/Mustache.relast')
...@@ -54,6 +72,7 @@ task relast(type: JavaExec) { ...@@ -54,6 +72,7 @@ task relast(type: JavaExec) {
file('./src/gen/jastadd/DumpAstResolverStubs.jrag')) file('./src/gen/jastadd/DumpAstResolverStubs.jrag'))
} }
// --- JastAdd ---
jastadd { jastadd {
configureModuleBuild() configureModuleBuild()
modules { modules {
...@@ -96,4 +115,70 @@ jastadd { ...@@ -96,4 +115,70 @@ jastadd {
jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"] jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
} }
// --- Tests ---
// --- Versioning and Publishing ---
group = 'de.tudresden.inf.st'
jar {
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
def versionFile = "src/main/resources/${project.getName()}Version.properties"
try {
def oldProps = new Properties()
file(versionFile).withInputStream { stream -> oldProps.load(stream) }
version = oldProps['version']
} catch (e) {
// this happens, if either the properties file is not present, or cannot be read from
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.", e)
}
task printVersion() {
doLast {
println(version)
}
}
task newVersion() {
doFirst {
def props = new Properties()
props['version'] = value
props.store(file(versionFile).newWriter(), null)
}
}
task setDevVersionForCI() {
doFirst {
def props = new Properties()
props['version'] = version + "-$System.env.CI_PIPELINE_IID"
props.store(file(versionFile).newWriter(), null)
}
}
publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
repositories {
maven {
url "https://git-st.inf.tu-dresden.de/api/v4/projects/$System.env.CI_PROJECT_ID/packages/maven"
credentials(HttpHeaderCredentials) {
name = 'Job-Token'
value = System.getenv("CI_JOB_TOKEN")
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}
// --- Task order ---
generateAst.dependsOn relast generateAst.dependsOn relast
publish.dependsOn jar
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> <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 ;
...@@ -35,7 +25,7 @@ DumpListRelation : DumpRelation ::= InnerDumpNode* ; ...@@ -35,7 +25,7 @@ DumpListRelation : DumpRelation ::= InnerDumpNode* ;
// type of NTA // type of NTA
InvisiblePath ::= InnerDumpNode* ; InvisiblePath ::= InnerDumpNode* ;
ClassAnalysisResult ::= AnalysedMethod* ; ClassAnalysisResult ::= ContainmentMethod:AnalysedMethod* OtherMethod:AnalysedMethod* ;
abstract AnalysedMethod ::= <Method:java.lang.reflect.Method> <Name> ; abstract AnalysedMethod ::= <Method:java.lang.reflect.Method> <Name> ;
abstract SingleChildMethod : AnalysedMethod ; abstract SingleChildMethod : AnalysedMethod ;
...@@ -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> ;
aspect Navigation {
/** Tests if TokenMethod is a IntrinsicTokenMethod.
* @return 'true' if this is a IntrinsicTokenMethod, otherwise 'false'
*/
syn boolean TokenMethod.isIntrinsicTokenMethod() = false;
eq IntrinsicTokenMethod.isIntrinsicTokenMethod() = true;
/** Tests if TokenMethod is a AttributeMethod.
* @return 'true' if this is a AttributeMethod, otherwise 'false'
*/
syn boolean TokenMethod.isAttributeMethod() = false;
eq AttributeMethod.isAttributeMethod() = true;
/** Tests if AnalysedMethod is a SingleChildMethod.
* @return 'true' if this is a SingleChildMethod, otherwise 'false'
*/
syn boolean AnalysedMethod.isSingleChildMethod() = false;
eq SingleChildMethod.isSingleChildMethod() = true;
/** Tests if AnalysedMethod is a ListChildMethod.
* @return 'true' if this is a ListChildMethod, otherwise 'false'
*/
syn boolean AnalysedMethod.isListChildMethod() = false;
eq ListChildMethod.isListChildMethod() = true;
/** Tests if AnalysedMethod is a SingleRelationMethod.
* @return 'true' if this is a SingleRelationMethod, otherwise 'false'
*/
syn boolean AnalysedMethod.isSingleRelationMethod() = false;
eq SingleRelationMethod.isSingleRelationMethod() = true;
/** Tests if AnalysedMethod is a ListRelationMethod.
* @return 'true' if this is a ListRelationMethod, otherwise 'false'
*/
syn boolean AnalysedMethod.isListRelationMethod() = false;
eq ListRelationMethod.isListRelationMethod() = true;
/** Tests if AnalysedMethod is a TokenMethod.
* @return 'true' if this is a TokenMethod, otherwise 'false'
*/
syn boolean AnalysedMethod.isTokenMethod() = false;
eq TokenMethod.isTokenMethod() = true;
/** Tests if DumpRelation is a DumpNormalRelation.
* @return 'true' if this is a DumpNormalRelation, otherwise 'false'
*/
syn boolean DumpRelation.isDumpNormalRelation() = false;
eq DumpNormalRelation.isDumpNormalRelation() = true;
/** Tests if DumpRelation is a DumpListRelation.
* @return 'true' if this is a DumpListRelation, otherwise 'false'
*/
syn boolean DumpRelation.isDumpListRelation() = false;
eq DumpListRelation.isDumpListRelation() = true;
/** Tests if DumpChildNode is a DumpNormalChildNode.
* @return 'true' if this is a DumpNormalChildNode, otherwise 'false'
*/
syn boolean DumpChildNode.isDumpNormalChildNode() = false;
eq DumpNormalChildNode.isDumpNormalChildNode() = true;
/** Tests if DumpChildNode is a DumpListChildNode.
* @return 'true' if this is a DumpListChildNode, otherwise 'false'
*/
syn boolean DumpChildNode.isDumpListChildNode() = false;
eq DumpListChildNode.isDumpListChildNode() = true;
/** Tests if ListChildMethod is a NormalListChildMethod.
* @return 'true' if this is a NormalListChildMethod, otherwise 'false'
*/
syn boolean ListChildMethod.isNormalListChildMethod() = false;
eq NormalListChildMethod.isNormalListChildMethod() = true;
/** Tests if ListChildMethod is a NTAListChildMethod.
* @return 'true' if this is a NTAListChildMethod, otherwise 'false'
*/
syn boolean ListChildMethod.isNTAListChildMethod() = false;
eq NTAListChildMethod.isNTAListChildMethod() = true;
/** Tests if SingleChildMethod is a NormalSingleChildMethod.
* @return 'true' if this is a NormalSingleChildMethod, otherwise 'false'
*/
syn boolean SingleChildMethod.isNormalSingleChildMethod() = false;
eq NormalSingleChildMethod.isNormalSingleChildMethod() = true;
/** Tests if SingleChildMethod is a NTASingleChildMethod.
* @return 'true' if this is a NTASingleChildMethod, otherwise 'false'
*/
syn boolean SingleChildMethod.isNTASingleChildMethod() = false;
eq NTASingleChildMethod.isNTASingleChildMethod() = true;
/** Tests if DumpToken is a DumpReferenceToken.
* @return 'true' if this is a DumpReferenceToken, otherwise 'false'
*/
syn boolean DumpToken.isDumpReferenceToken() = false;
eq DumpReferenceToken.isDumpReferenceToken() = true;
/** Tests if DumpToken is a DumpValueToken.
* @return 'true' if this is a DumpValueToken, otherwise 'false'
*/
syn boolean DumpToken.isDumpValueToken() = false;
eq DumpValueToken.isDumpValueToken() = true;
/** casts a TokenMethod into a IntrinsicTokenMethod if possible.
* @return 'this' cast to a IntrinsicTokenMethod or 'null'
*/
syn IntrinsicTokenMethod TokenMethod.asIntrinsicTokenMethod();
eq TokenMethod.asIntrinsicTokenMethod() = null;
eq IntrinsicTokenMethod.asIntrinsicTokenMethod() = this;
/** casts a TokenMethod into a AttributeMethod if possible.
* @return 'this' cast to a AttributeMethod or 'null'
*/
syn AttributeMethod TokenMethod.asAttributeMethod();
eq TokenMethod.asAttributeMethod() = null;
eq AttributeMethod.asAttributeMethod() = this;
/** casts a AnalysedMethod into a SingleChildMethod if possible.
* @return 'this' cast to a SingleChildMethod or 'null'
*/
syn SingleChildMethod AnalysedMethod.asSingleChildMethod();
eq AnalysedMethod.asSingleChildMethod() = null;
eq SingleChildMethod.asSingleChildMethod() = this;
/** casts a AnalysedMethod into a ListChildMethod if possible.
* @return 'this' cast to a ListChildMethod or 'null'
*/
syn ListChildMethod AnalysedMethod.asListChildMethod();
eq AnalysedMethod.asListChildMethod() = null;
eq ListChildMethod.asListChildMethod() = this;
/** casts a AnalysedMethod into a SingleRelationMethod if possible.
* @return 'this' cast to a SingleRelationMethod or 'null'
*/
syn SingleRelationMethod AnalysedMethod.asSingleRelationMethod();
eq AnalysedMethod.asSingleRelationMethod() = null;
eq SingleRelationMethod.asSingleRelationMethod() = this;
/** casts a AnalysedMethod into a ListRelationMethod if possible.
* @return 'this' cast to a ListRelationMethod or 'null'
*/
syn ListRelationMethod AnalysedMethod.asListRelationMethod();
eq AnalysedMethod.asListRelationMethod() = null;
eq ListRelationMethod.asListRelationMethod() = this;
/** casts a AnalysedMethod into a TokenMethod if possible.
* @return 'this' cast to a TokenMethod or 'null'
*/
syn TokenMethod AnalysedMethod.asTokenMethod();
eq AnalysedMethod.asTokenMethod() = null;
eq TokenMethod.asTokenMethod() = this;
/** casts a DumpRelation into a DumpNormalRelation if possible.
* @return 'this' cast to a DumpNormalRelation or 'null'
*/
syn DumpNormalRelation DumpRelation.asDumpNormalRelation();
eq DumpRelation.asDumpNormalRelation() = null;
eq DumpNormalRelation.asDumpNormalRelation() = this;
/** casts a DumpRelation into a DumpListRelation if possible.
* @return 'this' cast to a DumpListRelation or 'null'
*/
syn DumpListRelation DumpRelation.asDumpListRelation();
eq DumpRelation.asDumpListRelation() = null;
eq DumpListRelation.asDumpListRelation() = this;
/** casts a DumpChildNode into a DumpNormalChildNode if possible.
* @return 'this' cast to a DumpNormalChildNode or 'null'
*/
syn DumpNormalChildNode DumpChildNode.asDumpNormalChildNode();
eq DumpChildNode.asDumpNormalChildNode() = null;
eq DumpNormalChildNode.asDumpNormalChildNode() = this;
/** casts a DumpChildNode into a DumpListChildNode if possible.
* @return 'this' cast to a DumpListChildNode or 'null'
*/
syn DumpListChildNode DumpChildNode.asDumpListChildNode();
eq DumpChildNode.asDumpListChildNode() = null;
eq DumpListChildNode.asDumpListChildNode() = this;
/** casts a ListChildMethod into a NormalListChildMethod if possible.
* @return 'this' cast to a NormalListChildMethod or 'null'
*/
syn NormalListChildMethod ListChildMethod.asNormalListChildMethod();
eq ListChildMethod.asNormalListChildMethod() = null;
eq NormalListChildMethod.asNormalListChildMethod() = this;
/** casts a ListChildMethod into a NTAListChildMethod if possible.
* @return 'this' cast to a NTAListChildMethod or 'null'
*/
syn NTAListChildMethod ListChildMethod.asNTAListChildMethod();
eq ListChildMethod.asNTAListChildMethod() = null;
eq NTAListChildMethod.asNTAListChildMethod() = this;
/** casts a SingleChildMethod into a NormalSingleChildMethod if possible.
* @return 'this' cast to a NormalSingleChildMethod or 'null'
*/
syn NormalSingleChildMethod SingleChildMethod.asNormalSingleChildMethod();
eq SingleChildMethod.asNormalSingleChildMethod() = null;
eq NormalSingleChildMethod.asNormalSingleChildMethod() = this;
/** casts a SingleChildMethod into a NTASingleChildMethod if possible.
* @return 'this' cast to a NTASingleChildMethod or 'null'
*/
syn NTASingleChildMethod SingleChildMethod.asNTASingleChildMethod();
eq SingleChildMethod.asNTASingleChildMethod() = null;
eq NTASingleChildMethod.asNTASingleChildMethod() = this;
/** casts a DumpToken into a DumpReferenceToken if possible.
* @return 'this' cast to a DumpReferenceToken or 'null'
*/
syn DumpReferenceToken DumpToken.asDumpReferenceToken();
eq DumpToken.asDumpReferenceToken() = null;
eq DumpReferenceToken.asDumpReferenceToken() = this;
/** casts a DumpToken into a DumpValueToken if possible.
* @return 'this' cast to a DumpValueToken or 'null'
*/
syn DumpValueToken DumpToken.asDumpValueToken();
eq DumpToken.asDumpValueToken() = null;
eq DumpValueToken.asDumpValueToken() = this;
}
This diff is collapsed.
...@@ -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;
...@@ -369,7 +379,17 @@ public class DumpBuilder { ...@@ -369,7 +379,17 @@ public class DumpBuilder {
protected DumpAst build() { protected DumpAst build() {
if (result == null) { if (result == null) {
result = new DumpAst(); result = new DumpAst();
result.setPackageName(this.packageName == null ? this.target.getClass().getPackage().getName() : this.packageName); final String packageNameToUse;
if (this.packageName != null) {
packageNameToUse = this.packageName;
} else {
if (this.target == null) {
packageNameToUse = null;
} else {
packageNameToUse = this.target.getClass().getPackage().getName();
}
}
result.setPackageName(packageNameToUse);
result.setBuildConfig(this.buildConfig); result.setBuildConfig(this.buildConfig);
result.setPrintConfig(this.printConfig); result.setPrintConfig(this.printConfig);
try { try {
...@@ -400,11 +420,38 @@ public class DumpBuilder { ...@@ -400,11 +420,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 {}
...@@ -5,20 +5,9 @@ aspect Navigation { ...@@ -5,20 +5,9 @@ aspect Navigation {
syn boolean DumpRelation.isList() = false; syn boolean DumpRelation.isList() = false;
eq DumpListRelation.isList() = true; eq DumpListRelation.isList() = true;
// --- isDumpValueToken ---
syn boolean DumpToken.isDumpValueToken() = false;
eq DumpValueToken.isDumpValueToken() = true;
// --- asDumpValueToken ---
syn DumpValueToken DumpToken.asDumpValueToken() = null;
eq DumpValueToken.asDumpValueToken() = this;
// --- asDumpReferenceToken ---
syn DumpReferenceToken DumpToken.asDumpReferenceToken() = null;
eq DumpReferenceToken.asDumpReferenceToken() = this;
// --- 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 ---
...@@ -50,7 +39,7 @@ aspect Navigation { ...@@ -50,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) {
...@@ -59,9 +48,15 @@ aspect Navigation { ...@@ -59,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;
} }
...@@ -97,17 +92,4 @@ aspect Navigation { ...@@ -97,17 +92,4 @@ aspect Navigation {
coll java.util.List<TokenMethod> ClassAnalysisResult.tokenMethods() [new java.util.ArrayList<>()] root ClassAnalysisResult; coll java.util.List<TokenMethod> ClassAnalysisResult.tokenMethods() [new java.util.ArrayList<>()] root ClassAnalysisResult;
TokenMethod contributes this to ClassAnalysisResult.tokenMethods(); TokenMethod contributes this to ClassAnalysisResult.tokenMethods();
// --- isAttributeMethod ---
syn boolean TokenMethod.isAttributeMethod() = false;
eq AttributeMethod.isAttributeMethod() = true;
// --- isNTASingleChildMethod ---
syn boolean SingleChildMethod.isNTASingleChildMethod() = false;
eq NTASingleChildMethod.isNTASingleChildMethod() = true;
// --- isNTAListChildMethod ---
syn boolean ListChildMethod.isNTAListChildMethod() = false;
eq NTAListChildMethod.isNTAListChildMethod() = true;
} }
...@@ -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,9 +20,16 @@ aspect Printing { ...@@ -20,9 +20,16 @@ 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 ---
syn boolean InnerDumpNode.bothVisible() = !containingDumpNode().getInvisible() && !getDumpNode().getInvisible(); boolean ASTNode.bothVisible(DumpNode one, DumpNode two) {
syn boolean DumpNormalChildNode.bothVisible() = !containingDumpNode().getInvisible() && !getDumpNode().getInvisible(); return one != null && two != null && !one.getInvisible() && !two.getInvisible();
syn boolean DumpNormalRelation.bothVisible() = !containingDumpNode().getInvisible() && !getDumpNode().getInvisible(); }
syn boolean InnerDumpNode.bothVisible() = bothVisible(containingDumpNode(), getDumpNode());
syn boolean DumpNormalChildNode.bothVisible() = bothVisible(containingDumpNode(), getDumpNode());
syn boolean DumpNormalRelation.bothVisible() = bothVisible(containingDumpNode(), getDumpNode());
} }
@startuml @startuml
skinparam object<<null>> {
BorderColor transparent
BackgroundColor transparent
shadowing false
}
hide <<null>> stereotype
skinparam object<<NTA>> {
BorderColor {{{computedColor}}}
}
hide <<NTA>> stereotype
{{#PrintConfig}} {{#PrintConfig}}
scale {{Scale}} scale {{{scale}}}
{{#Headers}} {{#Headers}}
{{Value}} {{{value}}}
{{/Headers}} {{/Headers}}
{{/PrintConfig}} {{/PrintConfig}}
{{#DumpNodes}} {{#DumpNodes}}
{{^invisible}}
{{#isNull}}
object "null" as {{{name}}}<<null>>
{{/isNull}}
{{#isAstNode}} {{#isAstNode}}
{{^Invisible}} object "{{{labelAndTextColor}}}" as {{{name}}} {{{stereotypeList}}} {{#backgroundColor}}#{{{backgroundColor}}}{{/backgroundColor}} {
object "{{{labelAndTextColor}}}" as {{name}} {{#backgroundColor}}#{{{backgroundColor}}}{{/backgroundColor}} {
{{#DumpTokens}} {{#DumpTokens}}
{{#isDumpValueToken}} {{#isDumpValueToken}}
{{label}} = {{{Value}}} {{{label}}} = {{{value}}}
{{/isDumpValueToken}} {{/isDumpValueToken}}
{{/DumpTokens}} {{/DumpTokens}}
} }
{{/Invisible}}
{{/isAstNode}} {{/isAstNode}}
{{/invisible}}
{{/DumpNodes}} {{/DumpNodes}}
{{#DumpNodes}} {{#DumpNodes}}
{{#DumpTokens}} {{#DumpTokens}}
{{^Invisible}} {{^invisible}}
{{^isDumpValueToken}} {{^isDumpValueToken}}
{{outerNodeName}} ..> {{innerNodeName}} : {{label}} {{{outerNodeName}}} .{{#computed}}[#{{{computedColor}}}]{{/computed}}.> {{{innerNodeName}}} : {{{label}}}
{{/isDumpValueToken}} {{/isDumpValueToken}}
{{/Invisible}} {{/invisible}}
{{/DumpTokens}} {{/DumpTokens}}
{{#DumpChildNodes}} {{#DumpChildNodes}}
{{#isList}} {{#isList}}
{{#InnerDumpNodes}} {{#InnerDumpNodes}}
{{#bothVisible}} {{#bothVisible}}
{{outerNodeName}} *-- {{innerNodeName}} : {{label}} {{{outerNodeName}}} *-{{#computed}}[#{{{computedColor}}}]{{/computed}}- {{{innerNodeName}}} : {{{label}}}
{{/bothVisible}} {{/bothVisible}}
{{/InnerDumpNodes}} {{/InnerDumpNodes}}
{{/isList}} {{/isList}}
{{^isList}} {{^isList}}
{{#bothVisible}} {{#bothVisible}}
{{outerNodeName}} *-- {{innerNodeName}} : {{label}} {{{outerNodeName}}} *-{{#computed}}[#{{{computedColor}}}]{{/computed}}- {{{innerNodeName}}} : {{{label}}}
{{/bothVisible}} {{/bothVisible}}
{{/isList}} {{/isList}}
{{/DumpChildNodes}} {{/DumpChildNodes}}
...@@ -46,38 +60,38 @@ object "{{{labelAndTextColor}}}" as {{name}} {{#backgroundColor}}#{{{backgroundC ...@@ -46,38 +60,38 @@ object "{{{labelAndTextColor}}}" as {{name}} {{#backgroundColor}}#{{{backgroundC
{{#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}}
{{name}} -[hidden]right-> {{#successor}}{{name}}{{/successor}} {{{name}}} -[hidden]right-> {{#successor}}{{{name}}}{{/successor}}
{{/hasSuccessor}} {{/hasSuccessor}}
{{/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 #Fri Mar 11 12:41:31 CET 2022
version=0.3.6 version=1.0.0
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment