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

Merge branch 'dev' into 'main'

1.2.2

See merge request !12
parents 69402d31 13820cd1
Branches
No related tags found
1 merge request!121.2.2
Pipeline #14568 failed
Showing
with 447 additions and 383 deletions
......@@ -22,7 +22,7 @@ build:
- "./gradlew assemble"
artifacts:
paths:
- "dumpAst/src/gen"
- "dumpAst.base/src/gen"
expire_in: 1 week
test:
......@@ -65,7 +65,7 @@ ragdoc_build:
needs:
- build
script:
- JAVA_FILES=$(find dumpAst/src/ -name '*.java')
- JAVA_FILES=$(find dumpAst.base/src/ -name '*.java')
- echo $JAVA_FILES | wc -l
- /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES
artifacts:
......
[submodule "dumpAst/src/main/jastadd/mustache"]
path = dumpAst/src/main/jastadd/mustache
path = dumpAst.base/src/main/jastadd/mustache
url = ../mustache
# DumpAst
For documentation, please see https://jastadd.pages.st.inf.tu-dresden.de/relast2uml/
For documentation, please see https://jastadd.pages.st.inf.tu-dresden.de/dumpAst/
File moved
......@@ -74,21 +74,14 @@ jastadd {
modules {
//noinspection GroovyAssignabilityCheck
module("DumpAst") {
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 "dumpAst/src/gen/jastadd/**/*.ast"
include "dumpAst/src/gen/jastadd/**/*.jadd"
include "dumpAst/src/gen/jastadd/**/*.jrag"
basedir "."
include "src/main/jastadd/**/*.ast"
include "src/main/jastadd/**/*.jadd"
include "src/main/jastadd/**/*.jrag"
include "src/gen/jastadd/**/*.ast"
include "src/gen/jastadd/**/*.jadd"
include "src/gen/jastadd/**/*.jrag"
}
}
}
......@@ -126,7 +119,7 @@ task fatJar(type: Jar) {
}
}
def versionFile = "src/main/resources/${project.getName()}Version.properties"
def versionFile = "src/main/resources/${rootProject.getName()}Version.properties"
try {
def oldProps = new Properties()
......@@ -167,6 +160,8 @@ java {
publishing {
publications {
maven(MavenPublication) {
//noinspection GroovyAssignabilityCheck
artifactId = 'dumpAst'
from components.java
}
}
......
aspect ClassAnalysis {
syn nta ClassAnalysisResult DumpAst.analyzeClass(java.lang.Class<?> clazz) {
ClassAnalysisResult result = new ClassAnalysisResult();
String clazzName = clazz.getSimpleName();
java.util.List<String> targetOrder = targetOrder(clazz);
methodLoop: for (java.lang.reflect.Method method : clazz.getMethods()) {
for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
String canonicalName = annotation.annotationType().getCanonicalName();
if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
String simpleName = annotation.annotationType().getSimpleName();
String contextNameToAdd = null;
AnalysedMethod containmentMethodToAdd = null;
switch (simpleName) {
case "Child":
contextNameToAdd = invokeName(annotation);
NormalSingleChildMethod singleChildMethod = new NormalSingleChildMethod();
singleChildMethod.setMethod(method);
singleChildMethod.setName(contextNameToAdd);
containmentMethodToAdd = singleChildMethod;
break;
case "OptChild":
contextNameToAdd = invokeName(annotation);
try {
// the annotated method is "get???Opt", but we want "get???" and "has???"
java.lang.reflect.Method realGetter = clazz.getMethod("get" + contextNameToAdd);
java.lang.reflect.Method checkMethod = clazz.getMethod("has" + contextNameToAdd);
NormalOptChildMethod normalOptChildMethod = new NormalOptChildMethod();
normalOptChildMethod.setMethod(realGetter);
normalOptChildMethod.setCheckMethod(checkMethod);
normalOptChildMethod.setName(contextNameToAdd);
containmentMethodToAdd = normalOptChildMethod;
} catch (NoSuchMethodException e) {
System.err.println("Could not find getter for Opt-child " + contextNameToAdd + " in " + clazzName);
throw new RuntimeException(e);
}
break;
case "ListChild":
String listChildName = invokeName(annotation);
contextNameToAdd = listChildName;
NormalListChildMethod normalListChildMethod = new NormalListChildMethod();
normalListChildMethod.setMethod(method);
normalListChildMethod.setName(listChildName);
containmentMethodToAdd = normalListChildMethod;
break;
case "Token":
// heuristic for relations
String tokenName = invokeName(annotation);
if (tokenName.startsWith("_impl_")) {
String relationName = titleCase(tokenName.substring(6));
try {
java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName);
// normal get + token-name -> singleRelation
SingleRelationMethod singleRelationMethod = new SingleRelationMethod();
singleRelationMethod.setMethod(relationMethod);
singleRelationMethod.setName(relationName);
result.addOtherMethod(singleRelationMethod);
continue;
} catch (NoSuchMethodException e) {
// ignore, but we know this is probably not a single relation
}
// try list-relation next
try {
java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName + "List");
// normal get + token-name + "List" -> listRelation
ListRelationMethod listRelationMethod = new ListRelationMethod();
listRelationMethod.setMethod(relationMethod);
listRelationMethod.setName(relationName);
result.addOtherMethod(listRelationMethod);
continue;
} catch (NoSuchMethodException e) {
// ignore, but we know this is probably not a relation at all
}
}
IntrinsicTokenMethod tokenMethod = new IntrinsicTokenMethod();
tokenMethod.setMethod(method);
tokenMethod.setName(tokenName);
TokenMethod previousTokenMethodWithSameName = result.getTokenMethodWithName(tokenName);
if (method.getName().startsWith("refined__")) {
tokenMethod.setRefined(true);
// check for previous non-refined method with same name
if (previousTokenMethodWithSameName != null) {
// replace previous method instead of adding
result.setOtherMethod(tokenMethod, previousTokenMethodWithSameName.myIndex());
continue;
}
} else if (previousTokenMethodWithSameName != null && previousTokenMethodWithSameName.isIntrinsicTokenMethod() && previousTokenMethodWithSameName.asIntrinsicTokenMethod().getRefined()) {
continue;
}
result.addOtherMethod(tokenMethod);
break;
case "Attribute":
if (method.getParameterCount() > 0) {
// ignore parametrized attributes
continue;
}
String attributeName = method.getName();
boolean isNTA = (boolean) invokeMethod("isNTA", annotation);
if (isNTA) {
// remove leading "get"
if (attributeName.startsWith("get")) {
attributeName = attributeName.substring(3);
}
// remove trailing "List"
if (attributeName.endsWith("List")) {
attributeName = attributeName.substring(0, attributeName.length() - 4);
}
if (Iterable.class.isAssignableFrom(method.getReturnType())) {
NTAListChildMethod ntaListChildMethod = new NTAListChildMethod();
ntaListChildMethod.setMethod(method);
ntaListChildMethod.setName(attributeName);
result.addOtherMethod(ntaListChildMethod);
} else {
NTASingleChildMethod ntaSingleChildMethod = new NTASingleChildMethod();
ntaSingleChildMethod.setMethod(method);
ntaSingleChildMethod.setName(attributeName);
result.addOtherMethod(ntaSingleChildMethod);
}
} else {
// normal attribute
AttributeMethod attributeMethod = new AttributeMethod();
attributeMethod.setMethod(method);
attributeMethod.setName(attributeName);
result.addOtherMethod(attributeMethod);
}
break;
}
if (containmentMethodToAdd != null) {
int indexOfContextInTarget = targetOrder.indexOf(contextNameToAdd);
if (indexOfContextInTarget == 0) {
result.getContainmentMethodList().insertChild(containmentMethodToAdd, 0);
continue methodLoop;
}
if (indexOfContextInTarget == targetOrder.size() - 1) {
result.addContainmentMethod(containmentMethodToAdd);
continue methodLoop;
}
for (int i = 0, size = result.getNumContainmentMethod(); i < size; i++) {
String currentContextName = result.getContainmentMethod(i).getName();
int indexOfCurrentInTarget = targetOrder.indexOf(currentContextName);
if (indexOfCurrentInTarget > indexOfContextInTarget) {
result.getContainmentMethodList().insertChild(containmentMethodToAdd, i);
continue methodLoop;
}
}
result.addContainmentMethod(containmentMethodToAdd);
}
}
}
}
return result;
}
TokenMethod ClassAnalysisResult.getTokenMethodWithName(String tokenName) {
// this can not be an attribute, since ClassAnalysisResult changes, and we do not use incremental eval
for (AnalysedMethod otherMethod : getOtherMethodList()) {
if (otherMethod.isTokenMethod()) {
TokenMethod tokenMethod = otherMethod.asTokenMethod();
if (tokenMethod.getName().equals(tokenName)) {
return tokenMethod;
}
}
}
return null;
}
inh int AnalysedMethod.myIndex();
eq ClassAnalysisResult.getContainmentMethod(int index).myIndex() = index;
eq ClassAnalysisResult.getOtherMethod(int index).myIndex() = index;
syn java.util.List<String> DumpAst.targetOrder(Class<?> clazz) {
for (java.lang.reflect.Constructor<?> method : clazz.getConstructors()) {
for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
String canonicalName = annotation.annotationType().getCanonicalName();
if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
String simpleName = annotation.annotationType().getSimpleName();
if (simpleName.equals("Constructor")) {
return java.util.Arrays.asList((String[]) invokeMethod("name", annotation));
}
}
}
}
// there is no constructor with an annotation, iff the nonterminal has no children
return null;
}
private static String DumpAst.invokeName(java.lang.annotation.Annotation annotation) {
return (String) invokeMethod("name", annotation);
}
private static Object DumpAst.invokeMethod(String name, java.lang.annotation.Annotation annotation) {
try {
return annotation.annotationType().getMethod(name).invoke(annotation);
} catch (java.lang.reflect.InvocationTargetException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
// --- astNodeAnnotationPrefix ---
syn String DumpAst.astNodeAnnotationPrefix() = getPackageName() + ".ASTNodeAnnotation";
inh String DumpNode.astNodeAnnotationPrefix();
eq DumpAst.getDumpNode().astNodeAnnotationPrefix() = astNodeAnnotationPrefix();
}
......@@ -36,6 +36,10 @@ abstract SingleChildMethod : AnalysedMethod ;
NormalSingleChildMethod : SingleChildMethod ;
NTASingleChildMethod : SingleChildMethod ;
abstract OptChildMethod : AnalysedMethod ::= <CheckMethod:java.lang.reflect.Method> ;
NormalOptChildMethod : OptChildMethod ;
NTAOptChildMethod : OptChildMethod ;
abstract ListChildMethod : AnalysedMethod ;
NormalListChildMethod : ListChildMethod ;
NTAListChildMethod : ListChildMethod ;
......@@ -43,8 +47,9 @@ NTAListChildMethod : ListChildMethod ;
SingleRelationMethod : AnalysedMethod ;
ListRelationMethod : AnalysedMethod ;
// TODO can the refine bug also happen for refined attributes?
abstract TokenMethod : AnalysedMethod ;
IntrinsicTokenMethod : TokenMethod ;
IntrinsicTokenMethod : TokenMethod ::= <Refined:boolean> ;
AttributeMethod : TokenMethod ;
BuildConfig ::= StyleInformation
......
aspect Frontend {
// --- match{In,Ex}cludePatternCollection ---
syn PatternCollection BuildConfig.matchIncludePatternCollection(String typeName) {
for (TypePatternCollectionMapping mapping : getIncludeTypePatternList()) {
if (matches(mapping.typePattern(), typeName)) {
return mapping.getPatternCollection();
}
}
return null;
}
syn PatternCollection BuildConfig.matchExcludePatternCollection(String typeName) {
for (TypePatternCollectionMapping mapping : getExcludeTypePatternList()) {
if (matches(mapping.typePattern(), typeName)) {
return mapping.getPatternCollection();
}
}
return null;
}
static StyleInformation StyleInformation.createDefault() {
StyleInformation result = new StyleInformation();
result.setNameMethod(n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode()));
result.setBackgroundColorMethod(n -> "");
result.setTextColorMethod(n -> "");
result.setStereotypeMethod(n -> "");
result.setComputedColor("blue");
return result;
}
@FunctionalInterface
public interface StyleMethod<ASTNODE> {
String get(ASTNODE node);
}
@FunctionalInterface
public interface IncludeRelationMethod<ASTNODE> {
boolean shouldInclude(ASTNODE sourceNode, ASTNODE targetNode, String roleName);
}
@FunctionalInterface
public interface IncludeChildMethod<ASTNODE> {
boolean shouldInclude(ASTNODE parentNode, ASTNODE childNode, String contextName);
}
@FunctionalInterface
public interface IncludeAttributeMethod<ASTNODE> {
boolean shouldInclude(ASTNODE node, String attributeName, boolean isNTA, java.util.function.Supplier<Object> value);
}
@FunctionalInterface
public interface IncludeTokenMethod<ASTNODE> {
boolean shouldInclude(ASTNODE node, String tokenName, Object value);
}
}
......@@ -18,6 +18,12 @@ aspect Navigation {
syn boolean AnalysedMethod.isSingleChildMethod() = false;
eq SingleChildMethod.isSingleChildMethod() = true;
/** Tests if AnalysedMethod is a OptChildMethod.
* @return 'true' if this is a OptChildMethod, otherwise 'false'
*/
syn boolean AnalysedMethod.isOptChildMethod() = false;
eq OptChildMethod.isOptChildMethod() = true;
/** Tests if AnalysedMethod is a ListChildMethod.
* @return 'true' if this is a ListChildMethod, otherwise 'false'
*/
......@@ -123,6 +129,13 @@ aspect Navigation {
eq AnalysedMethod.asSingleChildMethod() = null;
eq SingleChildMethod.asSingleChildMethod() = this;
/** casts a AnalysedMethod into a OptChildMethod if possible.
* @return 'this' cast to a OptChildMethod or 'null'
*/
syn OptChildMethod AnalysedMethod.asOptChildMethod();
eq AnalysedMethod.asOptChildMethod() = null;
eq OptChildMethod.asOptChildMethod() = this;
/** casts a AnalysedMethod into a ListChildMethod if possible.
* @return 'this' cast to a ListChildMethod or 'null'
*/
......
aspect GenerationMustache {
aspect Mustache {
syn String DumpAst.toPlantUml() {
StringBuilder sb = new StringBuilder();
com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() {
......
......@@ -43,16 +43,16 @@ aspect Printing {
aspect Debugging {
syn String ClassAnalysisResult.prettyPrint() {
StringBuilder sb = new StringBuilder();
sb.append("ContainmentMethods:");
sb.append("- ContainmentMethods: ");
for (AnalysedMethod method : getContainmentMethodList()) {
sb.append(method.prettyPrint()).append(",");
sb.append("\n - ").append(method.prettyPrint());
}
if (getNumContainmentMethod() == 0) {
sb.append("none. ");
}
sb.append("other methods:");
sb.append("\n- Other methods: ");
for (AnalysedMethod method : getOtherMethodList()) {
sb.append(method.prettyPrint()).append(",");
sb.append("\n - ").append(method.prettyPrint());
}
if (getNumOtherMethod() == 0) {
sb.append("none.");
......
aspect TemplateContext {
// --- debug --- (mustache has printConfig as context)
syn boolean PrintConfig.debug() = buildConfig().getDebug();
// --- isNull ---
syn boolean DumpNode.isNull() {
return getObject() == null;
}
// --- isAstNode ---
syn boolean DumpNode.isAstNode() {
if (getObject() == null) {
return false;
}
Class<?> clazz = getObject().getClass();
for (java.lang.reflect.Method method : clazz.getMethods()) {
if ("init$Children".equals(method.getName()) && method.getParameterCount() == 0) {
return true;
}
}
return false;
}
// --- NTA: InvisiblePath ---
syn InvisiblePath DumpNode.getInvisiblePath() {
InvisiblePath result = new InvisiblePath();
for (DumpNode successor : reachableThroughInvisible()) {
result.addInnerRelationDumpNode(new InnerRelationDumpNode(successor));
}
return result;
}
// --- reachableThroughInvisible ---
syn java.util.List<DumpNode> DumpNode.reachableThroughInvisible() {
java.util.List<DumpNode> result = new java.util.ArrayList<>();
for (DumpChildNode childNode : getDumpChildNodeList()) {
for (DumpNode inner : childNode.innerNodes(false)) {
if (inner != null && inner.getInvisible()) {
result.addAll(inner.reachableThroughInvisible());
} else if (this.getInvisible()) {
result.add(inner);
}
}
}
return result;
}
// --- labelAndTextColor ---
syn String DumpNode.labelAndTextColor() {
if (getTextColor().isEmpty()) {
return getLabel();
} else {
return "<color:" + getTextColor() + ">" + getLabel() + "</color>";
}
}
// --- 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 ---
syn java.util.List<DumpNode> DumpNode.myChildren() {
java.util.List<DumpNode> result = new java.util.ArrayList<>();
for (DumpChildNode childNode : getDumpChildNodeList()) {
for (DumpNode inner : childNode.innerNodes(true)) {
result.add(inner);
}
}
return result;
}
// --- successor ---
syn DumpNode DumpNode.successor() {
if (container() == null) {
// not contained
return null;
}
java.util.List<DumpNode> siblingsAndMe = container().myChildren();
int indexOfMe = siblingsAndMe.indexOf(this);
if (indexOfMe == siblingsAndMe.size() - 1) {
// last child
return null;
}
return siblingsAndMe.get(indexOfMe + 1);
}
// --- hasSuccessor ---
syn boolean DumpNode.hasSuccessor() = successor() != null;
syn String DumpAst.computedColor() = getBuildConfig().getStyleInformation().getComputedColor();
}
aspect GenerationToYaml {
aspect ToYaml {
syn String DumpAst.printYaml(boolean prependCreationComment) {
Document doc = new Document();
doc.setRootElement(this.toYaml(false));
......@@ -240,7 +240,9 @@ aspect GenerationToYaml {
if (value.isEmpty()) {
return StringElement.of(value);
}
return refined(value);
return containsAny(value, ",#[{\"\n") ?
StringElement.of(value.replace("\n", "\\n").replace("\"", "\\\"")) :
ValueElement.of(value);
}
}
aspect GenerationBackend {
aspect Transform {
class DumpAst {
enum Source {
ROOT, NORMAL, RELATION
......@@ -11,7 +11,7 @@ aspect GenerationBackend {
public boolean computed;
public TransformationOptions asRelation() {
return fromSource(Source.RELATION, false).allowNullObjectsOnce();
return fromSource(Source.RELATION, false).computed(false).allowNullObjectsOnce();
}
public TransformationOptions asRoot() {
......@@ -123,9 +123,19 @@ aspect GenerationBackend {
System.out.println("for node " + obj + ", analysis was:\n" + car.prettyPrint());
}
for (AnalysedMethod containmentMethod : car.getContainmentMethodList()) {
if (containmentMethod.isSingleChildMethod()) {
// -- singleChild --
Object target = containmentMethod.getMethod().invoke(obj);
if (containmentMethod.isSingleChildMethod() || containmentMethod.isOptChildMethod()) {
// -- singleChild or optChild --
Object target;
if (containmentMethod.isOptChildMethod() && !((boolean) containmentMethod.asOptChildMethod().getCheckMethod().invoke(obj))) {
if (getBuildConfig().getExcludeNullNodes()) {
continue;
//target = containmentMethod.getMethod().invoke(obj);
} else {
target = null;
}
} else {
target = containmentMethod.getMethod().invoke(obj);
}
String childName = containmentMethod.getName();
if (!getBuildConfig().getIncludeChildMethod().shouldInclude(obj, target, childName)) {
continue;
......@@ -306,167 +316,6 @@ aspect GenerationBackend {
node.setManualStereotypes(getBuildConfig().getStyleInformation().getStereotypeMethod().get(obj));
}
syn nta ClassAnalysisResult DumpAst.analyzeClass(java.lang.Class<?> clazz) {
ClassAnalysisResult result = new ClassAnalysisResult();
String clazzName = clazz.getSimpleName();
java.util.List<String> targetOrder = targetOrder(clazz);
methodLoop: for (java.lang.reflect.Method method : clazz.getMethods()) {
for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
String canonicalName = annotation.annotationType().getCanonicalName();
if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
String simpleName = annotation.annotationType().getSimpleName();
String contextNameToAdd = null;
AnalysedMethod containmentMethodToAdd = null;
switch (simpleName) {
case "Child":
contextNameToAdd = invokeName(annotation);
NormalSingleChildMethod singleChildMethod = new NormalSingleChildMethod();
singleChildMethod.setMethod(method);
singleChildMethod.setName(contextNameToAdd);
containmentMethodToAdd = singleChildMethod;
break;
case "OptChild":
contextNameToAdd = invokeName(annotation);
try {
// the annotated method is "get???Opt", but we want "get???"
java.lang.reflect.Method realGetter = clazz.getMethod("get" + contextNameToAdd);
NormalSingleChildMethod normalSingleChildMethod = new NormalSingleChildMethod();
normalSingleChildMethod.setMethod(realGetter);
normalSingleChildMethod.setName(contextNameToAdd);
containmentMethodToAdd = normalSingleChildMethod;
} catch (NoSuchMethodException e) {
System.err.println("Could not find getter for Opt-child " + contextNameToAdd + " in " + clazzName);
throw new RuntimeException(e);
}
break;
case "ListChild":
String listChildName = invokeName(annotation);
contextNameToAdd = listChildName;
NormalListChildMethod normalListChildMethod = new NormalListChildMethod();
normalListChildMethod.setMethod(method);
normalListChildMethod.setName(listChildName);
containmentMethodToAdd = normalListChildMethod;
break;
case "Token":
// heuristic for relations
String tokenName = invokeName(annotation);
if (tokenName.startsWith("_impl_")) {
String relationName = titleCase(tokenName.substring(6));
try {
java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName);
// normal get + token-name -> singleRelation
SingleRelationMethod singleRelationMethod = new SingleRelationMethod();
singleRelationMethod.setMethod(relationMethod);
singleRelationMethod.setName(relationName);
result.addOtherMethod(singleRelationMethod);
continue;
} catch (NoSuchMethodException e) {
// ignore, but we know this is probably not a single relation
}
// try list-relation next
try {
java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName + "List");
// normal get + token-name + "List" -> listRelation
ListRelationMethod listRelationMethod = new ListRelationMethod();
listRelationMethod.setMethod(relationMethod);
listRelationMethod.setName(relationName);
result.addOtherMethod(listRelationMethod);
continue;
} catch (NoSuchMethodException e) {
// ignore, but we know this is probably not a relation at all
}
}
IntrinsicTokenMethod tokenMethod = new IntrinsicTokenMethod();
tokenMethod.setMethod(method);
tokenMethod.setName(tokenName);
result.addOtherMethod(tokenMethod);
break;
case "Attribute":
if (method.getParameterCount() > 0) {
// ignore parametrized attributes
continue;
}
String attributeName = method.getName();
boolean isNTA = (boolean) invokeMethod("isNTA", annotation);
if (isNTA) {
// remove leading "get"
if (attributeName.startsWith("get")) {
attributeName = attributeName.substring(3);
}
// remove trailing "List"
if (attributeName.endsWith("List")) {
attributeName = attributeName.substring(0, attributeName.length() - 4);
}
if (Iterable.class.isAssignableFrom(method.getReturnType())) {
NTAListChildMethod ntaListChildMethod = new NTAListChildMethod();
ntaListChildMethod.setMethod(method);
ntaListChildMethod.setName(attributeName);
result.addOtherMethod(ntaListChildMethod);
} else {
NTASingleChildMethod ntaSingleChildMethod = new NTASingleChildMethod();
ntaSingleChildMethod.setMethod(method);
ntaSingleChildMethod.setName(attributeName);
result.addOtherMethod(ntaSingleChildMethod);
}
} else {
// normal attribute
AttributeMethod attributeMethod = new AttributeMethod();
attributeMethod.setMethod(method);
attributeMethod.setName(attributeName);
result.addOtherMethod(attributeMethod);
}
break;
}
if (containmentMethodToAdd != null) {
int indexOfContextInTarget = targetOrder.indexOf(contextNameToAdd);
if (indexOfContextInTarget == 0) {
result.getContainmentMethodList().insertChild(containmentMethodToAdd, 0);
continue methodLoop;
}
if (indexOfContextInTarget == targetOrder.size() - 1) {
result.addContainmentMethod(containmentMethodToAdd);
continue methodLoop;
}
for (int i = 0, size = result.getNumContainmentMethod(); i < size; i++) {
String currentContextName = result.getContainmentMethod(i).getName();
int indexOfCurrentInTarget = targetOrder.indexOf(currentContextName);
if (indexOfCurrentInTarget > indexOfContextInTarget) {
result.getContainmentMethodList().insertChild(containmentMethodToAdd, i);
continue methodLoop;
}
}
result.addContainmentMethod(containmentMethodToAdd);
}
}
}
}
return result;
}
syn java.util.List<String> DumpAst.targetOrder(Class<?> clazz) {
for (java.lang.reflect.Constructor<?> method : clazz.getConstructors()) {
for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
String canonicalName = annotation.annotationType().getCanonicalName();
if (canonicalName.startsWith(astNodeAnnotationPrefix())) {
String simpleName = annotation.annotationType().getSimpleName();
if (simpleName.equals("Constructor")) {
return java.util.Arrays.asList((String[]) invokeMethod("name", annotation));
}
}
}
}
// there is no constructor with an annotation, iff the nonterminal has no children
return null;
}
private String DumpAst.titleCase(String s) {
if (s.isEmpty()) {
return s;
}
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
// TODO: add new attributes for: {token,child,relation,attribute,nta}Enabled(String parentType, String name). 1) just move implementation into this attribute. 2) add include/exclude on type-level to it.
// --- isTypeEnabled ---
......@@ -474,24 +323,6 @@ aspect GenerationBackend {
return !matches(getBuildConfig().typeIgnorePattern(), typeName);
}
// --- match{In,Ex}cludePatternCollection ---
syn PatternCollection BuildConfig.matchIncludePatternCollection(String typeName) {
for (TypePatternCollectionMapping mapping : getIncludeTypePatternList()) {
if (matches(mapping.typePattern(), typeName)) {
return mapping.getPatternCollection();
}
}
return null;
}
syn PatternCollection BuildConfig.matchExcludePatternCollection(String typeName) {
for (TypePatternCollectionMapping mapping : getExcludeTypePatternList()) {
if (matches(mapping.typePattern(), typeName)) {
return mapping.getPatternCollection();
}
}
return null;
}
// --- {typeIgnore,child,token,relation,attribute,nta}Pattern ---
syn java.util.regex.Pattern BuildConfig.typeIgnorePattern() = java.util.regex.Pattern.compile(getTypeIgnorePattern());
syn java.util.regex.Pattern PatternCollection.childPattern() = java.util.regex.Pattern.compile(getChildPattern());
......@@ -506,175 +337,9 @@ aspect GenerationBackend {
return p.matcher(input).matches();
}
// --- debug --- (mustache has printConfig as context)
syn boolean PrintConfig.debug() = buildConfig().getDebug();
private static String DumpAst.invokeName(java.lang.annotation.Annotation annotation) {
return (String) invokeMethod("name", annotation);
}
private static Object DumpAst.invokeMethod(String name, java.lang.annotation.Annotation annotation) {
try {
return annotation.annotationType().getMethod(name).invoke(annotation);
} catch (java.lang.reflect.InvocationTargetException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
// --- isNull ---
syn boolean DumpNode.isNull() {
return getObject() == null;
}
// --- isAstNode ---
syn boolean DumpNode.isAstNode() {
if (getObject() == null) {
return false;
}
Class<?> clazz = getObject().getClass();
for (java.lang.reflect.Method method : clazz.getMethods()) {
if ("init$Children".equals(method.getName()) && method.getParameterCount() == 0) {
return true;
}
}
return false;
}
// --- astNodeAnnotationPrefix ---
syn String DumpAst.astNodeAnnotationPrefix() = getPackageName() + ".ASTNodeAnnotation";
inh String DumpNode.astNodeAnnotationPrefix();
eq DumpAst.getDumpNode().astNodeAnnotationPrefix() = astNodeAnnotationPrefix();
// --- NTA: InvisiblePath ---
syn InvisiblePath DumpNode.getInvisiblePath() {
InvisiblePath result = new InvisiblePath();
for (DumpNode successor : reachableThroughInvisible()) {
result.addInnerRelationDumpNode(new InnerRelationDumpNode(successor));
}
return result;
}
// --- reachableThroughInvisible ---
syn java.util.List<DumpNode> DumpNode.reachableThroughInvisible() {
java.util.List<DumpNode> result = new java.util.ArrayList<>();
for (DumpChildNode childNode : getDumpChildNodeList()) {
for (DumpNode inner : childNode.innerNodes(false)) {
if (inner != null && inner.getInvisible()) {
result.addAll(inner.reachableThroughInvisible());
} else if (this.getInvisible()) {
result.add(inner);
}
}
}
return result;
}
// --- labelAndTextColor ---
syn String DumpNode.labelAndTextColor() {
if (getTextColor().isEmpty()) {
return getLabel();
} else {
return "<color:" + getTextColor() + ">" + getLabel() + "</color>";
}
}
// --- 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 ---
syn java.util.List<DumpNode> DumpNode.myChildren() {
java.util.List<DumpNode> result = new java.util.ArrayList<>();
for (DumpChildNode childNode : getDumpChildNodeList()) {
for (DumpNode inner : childNode.innerNodes(true)) {
result.add(inner);
}
}
return result;
}
// --- successor ---
syn DumpNode DumpNode.successor() {
if (container() == null) {
// not contained
return null;
}
java.util.List<DumpNode> siblingsAndMe = container().myChildren();
int indexOfMe = siblingsAndMe.indexOf(this);
if (indexOfMe == siblingsAndMe.size() - 1) {
// last child
return null;
}
return siblingsAndMe.get(indexOfMe + 1);
}
// --- hasSuccessor ---
syn boolean DumpNode.hasSuccessor() = successor() != null;
class TransformationTransferInformation {
java.util.Map<Object, DumpNode> transformed = new java.util.HashMap<>();
java.util.Map<DumpNode, Boolean> relationTargetsUnprocessed = new java.util.HashMap<>();
int nodeCounter = 0;
}
static StyleInformation StyleInformation.createDefault() {
StyleInformation result = new StyleInformation();
result.setNameMethod(n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode()));
result.setBackgroundColorMethod(n -> "");
result.setTextColorMethod(n -> "");
result.setStereotypeMethod(n -> "");
result.setComputedColor("blue");
return result;
}
syn String DumpAst.computedColor() = getBuildConfig().getStyleInformation().getComputedColor();
@FunctionalInterface
public interface StyleMethod<ASTNODE> {
String get(ASTNODE node);
}
@FunctionalInterface
public interface IncludeRelationMethod<ASTNODE> {
boolean shouldInclude(ASTNODE sourceNode, ASTNODE targetNode, String roleName);
}
@FunctionalInterface
public interface IncludeChildMethod<ASTNODE> {
boolean shouldInclude(ASTNODE parentNode, ASTNODE childNode, String contextName);
}
@FunctionalInterface
public interface IncludeAttributeMethod<ASTNODE> {
boolean shouldInclude(ASTNODE node, String attributeName, boolean isNTA, java.util.function.Supplier<Object> value);
}
@FunctionalInterface
public interface IncludeTokenMethod<ASTNODE> {
boolean shouldInclude(ASTNODE node, String tokenName, Object value);
}
}
aspect GenerationCommon {
aspect Util {
// --- find{In,Ex}cludePatternCollection ---
syn PatternCollection BuildConfig.findIncludePatternCollection(String typeRegex) {
for (TypePatternCollectionMapping mapping : getIncludeTypePatternList()) {
......@@ -8,6 +8,7 @@ aspect GenerationCommon {
}
return null;
}
syn PatternCollection BuildConfig.findExcludePatternCollection(String typeRegex) {
for (TypePatternCollectionMapping mapping : getExcludeTypePatternList()) {
if (mapping.getTypeRegex().equals(typeRegex)) {
......@@ -16,4 +17,11 @@ aspect GenerationCommon {
}
return null;
}
private String DumpAst.titleCase(String s) {
if (s.isEmpty()) {
return s;
}
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
}
File moved
......@@ -56,7 +56,6 @@ public class DumpBuilder {
this.target = target;
buildConfig = new BuildConfig();
buildConfig.setIncludeChildMethod((parentNode, childNode, contextName) -> {
System.out.printf("child: %s, %s, %s%n", parentNode, childNode, contextName);
// level 4: excluded for type? -> return no
PatternCollection excludeOnType = buildConfig.matchExcludePatternCollection(parentNode.getClass().getSimpleName());
if (excludeOnType != null && matches(excludeOnType.childPattern(), contextName)) {
......@@ -580,7 +579,7 @@ public class DumpBuilder {
}
/**
* Set the method defining, what name a node has (default: n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode())).
* Set the method defining, what name a node has (default: {@code n -> n == null ? "null" : n.getClass().getSimpleName() + "@" + Integer.toHexString(n.hashCode())}).
*
* <p>Example:<br>
* {@code builder.<ASTNode<?>>setNameMethod(n -> n.isA() ? "A" : "Not A")}
......@@ -594,7 +593,7 @@ public class DumpBuilder {
}
/**
* Set the method defining, what background color a node has (default: n -> "").
* Set the method defining, what background color a node has (default: {@code n -> ""}).
*
* <p>Example:<br>
* {@code builder.<ASTNode<?>>setBackgroundColorMethod(n -> n.isA() ? "red" : "blue")}
......@@ -608,7 +607,7 @@ public class DumpBuilder {
}
/**
* Set the method defining, what text color a node has (default: n -> "").
* Set the method defining, what text color a node has (default: {@code n -> ""}).
*
* <p>Example:<br>
* {@code builder.<ASTNode<?>>setTextColorMethod(n -> n.isA() ? "black" : "white")}
......@@ -622,7 +621,7 @@ public class DumpBuilder {
}
/**
* Set the method defining, what stereotype a node has (default: n -> "").
* Set the method defining, what stereotype a node has (default: {@code n -> ""}).
*
* <p>Example:<br>
* {@code builder.<ASTNode<?>>setStereotypeMethod(n -> n.isA() ? "MyStereoType" : "")}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment