Skip to content
Snippets Groups Projects
Commit 8b4c52ab authored by Johannes Mey's avatar Johannes Mey
Browse files

split backend into a file for each contained aspect

parent 7e9b8432
No related branches found
No related tags found
1 merge request!6split backend into a file for each contained aspect
Pipeline #5086 passed
aspect BackendAPI {
public void Relation.generateAPI(StringBuilder sb) {
sb.append(ind(1) + "// " + prettyPrint() + "\n");
getDirection().generateAPI(sb);
sb.append("\n");
}
public abstract void Direction.generateAPI(StringBuilder sb);
inh Relation Direction.relation();
eq Relation.getChild().relation() = this;
eq Program.getChild().relation() = null;
public String RelationComponent.nameCapitalized() {
return name().substring(0,1).toUpperCase() + name().substring(1);
}
}
aspect BackendAbstractGrammar {
public static String ASTNode.listClass = "ArrayList";
public static String ASTNode.jastAddListType = "List";
public static boolean ASTNode.resolverHelper = false;
public static boolean ASTNode.serializer = false;
public static boolean ASTNode.jsonPointer = false;
public static boolean ASTNode.manualReferences = false;
public static boolean ASTNode.useJastAddNames = false;
public String Program.generateAbstractGrammar() {
StringBuilder sb = new StringBuilder();
generateAbstractGrammar(sb);
return sb.toString();
}
public void Program.generateAbstractGrammar(StringBuilder sb) {
for (TypeDecl td: getTypeDecls()) {
td.generateAbstractGrammar(sb);
}
}
public void TypeDecl.generateUnresolvedClass(StringBuilder sb) {
if (getAbstract()) {
sb.append(ind(1) + "abstract ");
} else {
sb.append(ind(1));
}
sb.append("class " + "Unresolved$" + getID() + " extends " + getID() + " implements Unresolved$Node {\n");
sb.append(ind(2) + "private String unresolved$Token;\n");
sb.append(ind(2) + "public String getUnresolved$Token() {\n");
sb.append(ind(3) + "return unresolved$Token;\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "void setUnresolved$Token(String token) {\n");
sb.append(ind(3) + "this.unresolved$Token = token;\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "private boolean unresolved$ResolveOpposite;\n");
sb.append(ind(2) + "public boolean getUnresolved$ResolveOpposite() {\n");
sb.append(ind(3) + "return unresolved$ResolveOpposite;\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "void setUnresolved$ResolveOpposite(boolean resolveOpposite) {\n");
sb.append(ind(3) + "this.unresolved$ResolveOpposite = resolveOpposite;\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "Unresolved$Node " + getID() + ".as$Unresolved() {\n");
sb.append(ind(2) + "return null;\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "Unresolved$Node Unresolved$" + getID() + ".as$Unresolved() {\n");
sb.append(ind(2) + "return this;\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "boolean " + getID() + ".is$Unresolved() {\n");
sb.append(ind(2) + "return false;\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "boolean Unresolved$" + getID() + ".is$Unresolved() {\n");
sb.append(ind(2) + "return true;\n");
sb.append(ind(1) + "}\n");
}
public void TypeDecl.generateAbstractGrammar(StringBuilder sb) {
if (getAbstract()) {
sb.append("abstract ");
}
sb.append(getID());
if (hasSuper()) {
sb.append(" : " + getSuper());
}
if (getNumComponent() > 0 || relationComponents().size() > 0) {
sb.append(" ::=");
}
for (Component c: getComponents()) {
sb.append(" ");
sb.append(c.generateAbstractGrammar());
}
for (RelationComponent c: relationComponents()) {
sb.append(" ");
sb.append(c.generateAbstractGrammar());
}
sb.append(";\n");
}
public String Component.generateAbstractGrammar() {
if (getID().equals(getTypeUse().toString())) {
return getTypeUse().toString();
} else {
return getID() + ":" + getTypeUse();
}
}
public String ListComponent.generateAbstractGrammar() {
return super.generateAbstractGrammar() + "*";
}
public String OptComponent.generateAbstractGrammar() {
return "[" + super.generateAbstractGrammar() + "]";
}
public String NTAComponent.generateAbstractGrammar() {
return "/" + super.generateAbstractGrammar() + "/";
}
public String NTAListComponent.generateAbstractGrammar() {
return "/" + super.generateAbstractGrammar() + "*/";
}
public String NTAOptComponent.generateAbstractGrammar() {
return "/[" + super.generateAbstractGrammar() + "]/";
}
public String TokenComponent.generateAbstractGrammar() {
return "<" + getID() + ":" + getTypeUse() + ">";
}
public String NTATokenComponent.generateAbstractGrammar() {
return "/<" + getID() + ":" + getTypeUse() + ">/";
}
public String RelationComponent.generateAbstractGrammar() {
return "<" + getImplAttributeName() + ":" + ofTypeDecl() + ">";
}
public String ManyRelationComponent.generateAbstractGrammar() {
return "<" + getImplAttributeName() + ":" + ASTNode.listClass + "<" + ofTypeDecl() + ">>";
}
public String RelationComponent.getImplAttributeName() {
return "_impl_" + getID();
}
public String RelationComponent.getImplAttributeField() {
// tt.bind("TypeInSignature", ASTNode.convTypeNameToSignature(type()));
return "token" + ofTypeDecl() + "__impl_" + getID();
}
public String ManyRelationComponent.getImplAttributeField() {
// tt.bind("TypeInSignature", ASTNode.convTypeNameToSignature(type()));
return "token" + listClass + "_" + ofTypeDecl() + "___impl_" + getID();
}
}
aspect BackendAspect {
public String Program.generateAspect() {
StringBuilder sb = new StringBuilder();
generateAspect(sb);
return sb.toString();
}
public void Program.generateAspect(StringBuilder sb) {
sb.append("import java.util.ArrayList;\n");
sb.append("import java.util.Collections;\n");
sb.append("import java.time.Instant;\n");
sb.append("import java.time.Period;\n");
sb.append("aspect RelAstAPI {\n");
for (TypeDecl td: getTypeDecls()) {
if (td.needsConstructor()) {
td.generateConstructor(sb);
}
}
for (Relation r: getRelations()) {
r.generateAPI(sb);
}
generateLowerBoundCheck(sb);
sb.append(ind(1) + "public static void ASTNode.assertNotNull(Object obj) {\n");
sb.append(ind(2) + "if (obj == null) {\n");
sb.append(ind(3) + "throw new NullPointerException();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append("}\n");
}
public void TypeDecl.generateConstructor(StringBuilder sb) {
sb.append(ind(1) + "public " + getID() + "." + getID() + "(");
int i = 0;
for (Component c: componentsTransitive()) {
sb.append(c.constructorParameter());
if (++i < componentsTransitive().size()) {
sb.append(", ");
}
}
sb.append(") {\n");
for (Component c: componentsTransitive()) {
sb.append(ind(2) + c.constructorSetMethod() + "(" + c.getID() + ");\n");
}
sb.append(ind(1) + "}\n");
}
public String Component.constructorParameter() {
return getTypeUse() + " " + getID();
}
public String ListComponent.constructorParameter() {
return ASTNode.jastAddListType + "<" + getTypeUse() + "> " + getID();
}
public String OptComponent.constructorParameter() {
return "Opt<" + getTypeUse() + "> " + getID();
}
public String Component.constructorSetMethod() {
return "set" + getID();
}
public String ListComponent.constructorSetMethod() {
return "set" + getID() + "List";
}
public String OptComponent.constructorSetMethod() {
return "set" + getID() + "Opt";
}
}
aspect BackendBidirectionalAPI {
public void Bidirectional.generateAPI(StringBuilder sb) {
RelationComponent l = relation().getLeft();
RelationComponent r = relation().getRight();
if (l.multiplicityOne()) {
if (r.multiplicityOne()) {
l.generateBiOneOne(sb, false);
r.generateBiOneOne(sb, false);
} else if (r.multiplicityOpt()) {
l.generateBiOneOne(sb, false);
r.generateBiOneOne(sb, true);
} else if (r.multiplicityMany()) {
l.generateBiOneMany(sb, false);
r.generateBiManyOne(sb, l);
}
} else if (l.multiplicityOpt()) {
if (r.multiplicityOne()) {
l.generateBiOneOne(sb, true);
r.generateBiOneOne(sb, false);
} else if (r.multiplicityOpt()) {
l.generateBiOneOne(sb, true);
r.generateBiOneOne(sb, true);
} else if (r.multiplicityMany()) {
l.generateBiOneMany(sb, true);
r.generateBiManyOne(sb, l);
}
} else if (l.multiplicityMany()) {
if (r.multiplicityOne()) {
l.generateBiManyOne(sb, r);
r.generateBiOneMany(sb, false);
} else if (r.multiplicityOpt()) {
l.generateBiManyOne(sb, r);
r.generateBiOneMany(sb, true);
} else if (r.multiplicityMany()) {
l.generateBiManyMany(sb, r);
r.generateBiManyMany(sb, l);
}
}
}
public void RelationComponent.generateBiOneOne(StringBuilder sb, boolean isOpt) {
// Get
generateGetOne(sb);
// Set
sb.append(ind(1) + "public " + getTypeUse().decl() + " " + getTypeUse().decl());
sb.append(".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
if (!isOpt) {
sb.append(ind(2) + "assertNotNull(o);\n");
}
// unset the old opposite
sb.append(ind(2) + "if (" + getImplAttributeField() + " != null) {\n");
sb.append(ind(3) + "" + getImplAttributeField() + ".set" + otherSide().getImplAttributeName() + "(null);\n");
sb.append(ind(2) + "}\n");
if (resolverHelper | serializer) {
sb.append(ind(2) + "if (o != null && !o.is$Unresolved() && o." + otherSide().getImplAttributeField() + " != null) {\n");
} else {
sb.append(ind(2) + "if (o != null && o." + otherSide().getImplAttributeField() + " != null) {\n");
}
sb.append(ind(3) + "o." + otherSide().getImplAttributeField() + ".set" + getImplAttributeName() + "(null);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
if (resolverHelper | serializer) {
sb.append(ind(2) + "if (o == null || !o.is$Unresolved()) {\n");
if (isOpt) {
sb.append(ind(3) + "if (o != null) {\n");
sb.append(ind(4) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
sb.append(ind(3) + "}\n");
} else {
sb.append(ind(3) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
}
sb.append(ind(2) + "}\n");
} else {
if (isOpt) {
sb.append(ind(2) + "if (o != null) {\n");
sb.append(ind(3) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
sb.append(ind(2) + "}\n");
} else {
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
}
}
sb.append(ind(2) + "return this;\n");
sb.append(ind(1) + "}\n");
if (isOpt) {
generateExtraOptAPI(sb);
}
}
public void RelationComponent.generateBiManyMany(StringBuilder sb, RelationComponent opposite) {
// Get
sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl() + ".");
if (useJastAddNames) {
// getXs
sb.append("get" + nameCapitalized() + "s() {\n");
sb.append(ind(2) + "return get" + nameCapitalized() + "List();\n");
sb.append(ind(1) + "}\n");
// getXList
sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl());
sb.append(".get" + nameCapitalized() + "List() {\n");
} else {
sb.append(name() + "() {\n");
}
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> l = get" + getImplAttributeName() + "();\n");
// resolve the entire list
if (resolverHelper | serializer) {
sb.append(ind(2) + "if (l != null) {\n");
sb.append(ind(3) + "boolean changed = false;\n");
sb.append(ind(3) + "for (int i = 0; i < l.size(); i++) {\n");
sb.append(ind(4) + ofTypeDecl() + " element = l.get(i);\n");
sb.append(ind(4) + "if (element.is$Unresolved()) {\n");
sb.append(ind(5) + "changed = true;\n");
sb.append(ind(5) + ofTypeDecl() + " resolvedElement = resolve" + nameCapitalized() + "ByToken(element.as$Unresolved().getUnresolved$Token(), i);\n");
sb.append(ind(5) + "if (resolvedElement != null && element.as$Unresolved().getUnresolved$ResolveOpposite()) {\n");
sb.append(ind(6) + ASTNode.listClass + "<" + getTypeUse().decl() + "> otherList = resolvedElement." + opposite.getImplAttributeField() + ";\n");
sb.append(ind(6) + "if (otherList == null) {\n");
sb.append(ind(7) + "otherList = new " + listClass + "<>();\n");
sb.append(ind(6) + "}\n");
sb.append(ind(6) + "otherList.add(this);\n");
sb.append(ind(6) + "resolvedElement.set" + opposite.getImplAttributeName() + "(otherList);\n");
sb.append(ind(5) + "}\n");
sb.append(ind(5) + "l.set(i, resolvedElement);\n");
sb.append(ind(4) + "}\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "if (changed) {\n");
sb.append(ind(4) + "set" + getImplAttributeName() + "(l);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
}
sb.append(ind(2) + "return l != null ? Collections.unmodifiableList(l) : Collections.emptyList();\n");
sb.append(ind(1) + "}\n");
// Add
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add");
if (!useJastAddNames) {
sb.append("To");
}
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + ASTNode.listClass + "<" + otherSide().ofTypeDecl() + "> list2 = o." + otherSide().getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list2 == null) {\n");
sb.append(ind(3) + "list2 = new "+ ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(o);\n");
sb.append(ind(2) + "list2.add(this);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(list2);\n");
sb.append(ind(1) + "}\n");
// Insert / add at specific position
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add");
if (!useJastAddNames) {
sb.append("To");
}
sb.append(nameCapitalized() + "(int index, " + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + ASTNode.listClass + "<" + otherSide().ofTypeDecl() + "> list2 = o."
+ otherSide().getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list2 == null) {\n");
sb.append(ind(3) + "list2 = new "+ ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(index, o);\n");
sb.append(ind(2) + "list2.add(this);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(list2);\n");
sb.append(ind(1) + "}\n");
// Remove
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".remove");
if (!useJastAddNames) {
sb.append("From");
}
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
sb.append(ind(3) + ASTNode.listClass + "<" + otherSide().ofTypeDecl() + "> list2 = o."
+ otherSide().getImplAttributeField() + ";\n");
sb.append(ind(3) + "if (list2 != null) list2.remove(this);\n");
sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(3) + "o.set" + otherSide().getImplAttributeName() + "(list2);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateBiManyOne(StringBuilder sb, RelationComponent opposite) {
// Get
sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl() + ".");
if (useJastAddNames) {
// getXs
sb.append("get" + nameCapitalized() + "s() {\n");
sb.append(ind(2) + "return get" + nameCapitalized() + "List();\n");
sb.append(ind(1) + "}\n");
// getXList
sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl());
sb.append(".get" + nameCapitalized() + "List() {\n");
} else {
sb.append(name() + "() {\n");
}
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> l = get" + getImplAttributeName() + "();\n");
// resolve the entire list
if (resolverHelper | serializer) {
sb.append(ind(2) + "if (l != null) {\n");
sb.append(ind(3) + "boolean changed = false;\n");
sb.append(ind(3) + "for (int i = 0; i < l.size(); i++) {\n");
sb.append(ind(4) + ofTypeDecl() + " element = l.get(i);\n");
sb.append(ind(4) + "if (element.is$Unresolved()) {\n");
sb.append(ind(5) + "changed = true;\n");
sb.append(ind(5) + ofTypeDecl() + " resolvedElement = resolve" + nameCapitalized() + "ByToken(element.as$Unresolved().getUnresolved$Token(), i);\n");
sb.append(ind(5) + "if (element.as$Unresolved().getUnresolved$ResolveOpposite()) {\n");
sb.append(ind(6) + getTypeUse().decl() + " oldTarget = resolvedElement." + opposite.getImplAttributeField() + ";\n");
sb.append(ind(6) + "if (oldTarget != null && oldTarget != this) {\n");
sb.append(ind(7) + "oldTarget." + getImplAttributeField() + ".remove(resolvedElement);\n");
sb.append(ind(6) + "}\n");
sb.append(ind(6) + "if (oldTarget == this) {\n");
sb.append(ind(7) + "l.remove(i);\n");
sb.append(ind(7) + "i--;\n");
sb.append(ind(6) + "} else {\n");
sb.append(ind(7) + "resolvedElement.set" + opposite.getImplAttributeName() + "(this);\n");
sb.append(ind(7) + "l.set(i, resolvedElement);\n");
sb.append(ind(6) + "}\n");
sb.append(ind(5) + "} else {\n");
sb.append(ind(6) + "l.set(i, resolvedElement);\n");
sb.append(ind(5) + "}\n");
sb.append(ind(4) + "}\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "if (changed) {\n");
sb.append(ind(4) + "set" + getImplAttributeName() + "(l);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
}
sb.append(ind(2) + "return l != null ? Collections.unmodifiableList(l) : Collections.emptyList();\n");
sb.append(ind(1) + "}\n");
// Add
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add");
if (!useJastAddNames) {
sb.append("To");
}
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + "if (o != null && o." + otherSide().getImplAttributeField() + " != null) {\n");
sb.append(ind(3) + ASTNode.listClass + "<" + ofTypeDecl() + "> list2 = o."
+ otherSide().getImplAttributeField() + "." + getImplAttributeField() + ";\n");
sb.append(ind(3) + "if (list2.remove(o))\n");
sb.append(ind(4) + "o." + otherSide().getImplAttributeField()
+ ".set" + getImplAttributeName() + "(list2);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(o);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
sb.append(ind(1) + "}\n");
// Insert / add at specific position
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add");
if (!useJastAddNames) {
sb.append("To");
}
sb.append(nameCapitalized() + "(int index, " + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + "if (o != null && o." + otherSide().getImplAttributeField() + " != null) {\n");
sb.append(ind(3) + ASTNode.listClass + "<" + ofTypeDecl() + "> list2 = o." + otherSide().getImplAttributeField() + "." + getImplAttributeField() + ";\n");
sb.append(ind(3) + "if (list2.remove(o))\n");
sb.append(ind(4) + "o." + otherSide().getImplAttributeField() + ".set" + getImplAttributeName() + "(list2);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(index, o);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
sb.append(ind(1) + "}\n");
// Remove
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".remove");
if (!useJastAddNames) {
sb.append("From");
}
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(3) + "if (o." + otherSide().getImplAttributeField() + " == this) {\n");
sb.append(ind(4) + "o.set" + otherSide().getImplAttributeName() + "(null);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateBiOneMany(StringBuilder sb, boolean isOpt) {
// Get
generateGetOne(sb);
// Set
sb.append(ind(1) + "public " + getTypeUse().decl() + " " + getTypeUse().decl() + ".set" + nameCapitalized()
+ "(" + ofTypeDecl() + " o) {\n");
if (!isOpt) {
sb.append(ind(2) + "assertNotNull(o);\n");
}
sb.append(ind(2) + "if (" + getImplAttributeField() + " != null) {\n");
sb.append(ind(3) + ASTNode.listClass + "<" + getTypeUse().decl() + "> list2 = " + getImplAttributeField()
+ "." + otherSide().getImplAttributeField() + ";\n");
sb.append(ind(3) + "list2.remove(this);\n");
sb.append(ind(3) + getImplAttributeField() + "." + "set"
+ otherSide().getImplAttributeName() + "(list2);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
int ind = isOpt ? 3 : 2;
if (isOpt) {
sb.append(ind(2) + "if (o != null) {\n");
}
sb.append(ind(ind) + ASTNode.listClass + "<" + getTypeUse().decl() + "> list = o."
+ otherSide().getImplAttributeField() + ";\n");
sb.append(ind(ind) + "if (list == null) {\n");
sb.append(ind(ind+1) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(ind) + "}\n");
sb.append(ind(ind) + "list.add(this);\n");
sb.append(ind(ind) + "o.set" + otherSide().getImplAttributeName() + "(list);\n");
if (isOpt) {
sb.append(ind(2) + "}\n");
}
sb.append(ind(2) + "return this;\n");
sb.append(ind(1) + "}\n");
if (isOpt) {
generateExtraOptAPI(sb);
}
}
}
aspect BackendDirectedAPI {
public void RightDirection.generateAPI(StringBuilder sb) {
relation().getLeft().generateDirectedAPI(sb);
}
public void LeftDirection.generateAPI(StringBuilder sb) {
relation().getRight().generateDirectedAPI(sb);
}
public abstract void RelationComponent.generateDirectedAPI(StringBuilder sb);
public void OneRelationComponent.generateDirectedAPI(StringBuilder sb) {
generateDirectedZeroOneAPI(sb, false);
}
public void OptionalRelationComponent.generateDirectedAPI(StringBuilder sb) {
generateDirectedZeroOneAPI(sb, true);
generateExtraOptAPI(sb);
}
public void RelationComponent.generateDirectedZeroOneAPI(StringBuilder sb, boolean optional) {
// Get
generateGetOne(sb);
// Set
sb.append(ind(1) + "public " + getTypeUse().decl() + " " + getTypeUse().decl());
sb.append(".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
if (!optional) {
sb.append(ind(2) + "assertNotNull(o);\n");
}
sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
sb.append(ind(2) + "return this;\n");
sb.append(ind(1) + "}\n");
}
public void ManyRelationComponent.generateDirectedAPI(StringBuilder sb) {
// Get
sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl() + ".");
if (useJastAddNames) {
// getXs
sb.append("get" + nameCapitalized() + "s() {\n");
sb.append(ind(2) + "return get" + nameCapitalized() + "List();\n");
sb.append(ind(1) + "}\n");
// getXList
sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + getTypeUse().decl());
sb.append(".get" + nameCapitalized() + "List() {\n");
} else {
sb.append(name() + "() {\n");
}
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> l = get" + getImplAttributeName() + "();\n");
// resolve the entire list
if (resolverHelper | serializer) {
sb.append(ind(2) + "if (l != null) {\n");
sb.append(ind(3) + "boolean changed = false;\n");
sb.append(ind(3) + "for (int i = 0; i < l.size(); i++) {\n");
sb.append(ind(4) + ofTypeDecl() + " element = l.get(i);\n");
sb.append(ind(4) + "if (element.is$Unresolved()) {\n");
sb.append(ind(5) + "changed = true;\n");
sb.append(ind(5) + ofTypeDecl() + " resolvedElement = resolve" + nameCapitalized() + "ByToken(element.as$Unresolved().getUnresolved$Token(), i);\n");
sb.append(ind(5) + "l.set(i, resolvedElement);\n");
sb.append(ind(4) + "}\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "if (changed) {\n");
sb.append(ind(4) + "set" + getImplAttributeName() + "(l);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
}
sb.append(ind(2) + "return l != null ? Collections.unmodifiableList(l) : Collections.emptyList();\n");
sb.append(ind(1) + "}\n");
// Add
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add");
if (!useJastAddNames) {
sb.append("To");
}
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(o);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(1) + "}\n");
// Insert / add at specific position
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".add");
if (!useJastAddNames) {
sb.append("To");
}
sb.append(nameCapitalized() + "(int index, " + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(index, o);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(1) + "}\n");
// Remove
sb.append(ind(1) + "public void " + getTypeUse().decl() + ".remove");
if (!useJastAddNames) {
sb.append("From");
}
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = " + getImplAttributeField() + ";\n");
sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateGetOne(StringBuilder sb) {
sb.append(ind(1) + "public " + ofTypeDecl() + " " + getTypeUse().decl() + ".");
if (useJastAddNames) {
sb.append("get" + nameCapitalized());
} else {
sb.append(name());
}
sb.append("() {\n");
if (resolverHelper | serializer) {
sb.append(ind(2) + "if (" + getImplAttributeField() + " != null && " + getImplAttributeField() + ".is$Unresolved()) {\n");
sb.append(ind(3) + "if (" + getImplAttributeField() + ".as$Unresolved().getUnresolved$ResolveOpposite()) {\n");
sb.append(ind(4) + "set" + nameCapitalized() + "(resolve" + nameCapitalized() + "ByToken(" + getImplAttributeField() + ".as$Unresolved().getUnresolved$Token()));\n");
sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "set" + getImplAttributeName() + "(resolve" + nameCapitalized() + "ByToken(" + getImplAttributeField() + ".as$Unresolved().getUnresolved$Token()));\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
}
sb.append(ind(2) + "return get" + getImplAttributeName() + "();\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateExtraOptAPI(StringBuilder sb) {
// has
sb.append(ind(1) + "public boolean " + getTypeUse().decl());
sb.append(".has" + nameCapitalized() + "() {\n");
sb.append(ind(2) + "return ");
if (useJastAddNames) {
sb.append("get" + nameCapitalized());
} else {
sb.append(name());
}
sb.append("() != null;\n");
sb.append(ind(1) + "}\n");
// clear
sb.append(ind(1) + "public void " + getTypeUse().decl());
sb.append(".clear" + nameCapitalized() + "() {\n");
sb.append(ind(2) + "set" + nameCapitalized() + "(null);\n");
sb.append(ind(1) + "}\n");
}
}
aspect LowerBoundCheck {
public void Program.generateLowerBoundCheck(StringBuilder sb) {
sb.append(ind(1) + "public boolean ASTNode.violatesLowerBounds() {\n");
sb.append(ind(2) + "return !getLowerBoundsViolations().isEmpty();\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public java.util.List<Pair<ASTNode, String>> "
+ "ASTNode.getLowerBoundsViolations() {\n");
sb.append(ind(2) + "ArrayList<Pair<ASTNode, String>> list = new ArrayList<>();\n");
sb.append(ind(2) + "computeLowerBoundsViolations(list);\n");
sb.append(ind(2) + "return list;\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.computeLowerBoundsViolations("
+ "java.util.List<Pair<ASTNode, String>> list) {\n");
sb.append(ind(2) + "for (int i = 0; i < getNumChildNoTransform(); i++) {\n");
sb.append(ind(3) + "getChildNoTransform(i).computeLowerBoundsViolations(list);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
for (TypeDecl td: getTypeDecls()) {
td.generateLowerBoundCheck(sb);
}
generatePairClass(sb);
}
public void TypeDecl.generateLowerBoundCheck(StringBuilder sb) {
if (!oneRelationComponents().isEmpty()) {
sb.append(ind(1) + "public void " + getID() + ".computeLowerBoundsViolations(" +
"java.util.List<Pair<ASTNode, String>> list) {\n");
for (OneRelationComponent o: oneRelationComponents()) {
o.generateLowerBoundCheck(sb);
}
sb.append(ind(2) + "super.computeLowerBoundsViolations(list);\n");
sb.append(ind(1) + "}\n");
}
}
public void OneRelationComponent.generateLowerBoundCheck(StringBuilder sb) {
sb.append(ind(2) + "if (");
if (useJastAddNames) {
sb.append("get" + nameCapitalized());
} else {
sb.append(name());
}
sb.append("() == null) {\n");
sb.append(ind(3) + "list.add(new Pair<>(this, \"" + name() + "\"));\n");
sb.append(ind(2) + "}\n");
}
public void Program.generatePairClass(StringBuilder sb) {
sb.append(ind(1) + "public class Pair<T1, T2> {\n");
sb.append(ind(2) + "public final T1 _1;\n");
sb.append(ind(2) + "public final T2 _2;\n");
// Constructor
sb.append(ind(2) + "public Pair(T1 _1, T2 _2) {\n");
sb.append(ind(3) + "ASTNode.assertNotNull(_1);\n");
sb.append(ind(3) + "ASTNode.assertNotNull(_2);\n");
sb.append(ind(3) + "this._1 = _1;\n");
sb.append(ind(3) + "this._2 = _2;\n");
sb.append(ind(2) + "}\n");
// equals
sb.append(ind(2) + "public boolean equals(Object other) {\n");
sb.append(ind(3) + "if (other instanceof Pair) {\n");
sb.append(ind(4) + "Pair<?,?> p = (Pair<?,?>) other;\n");
sb.append(ind(4) + "return _1.equals(p._1) && _2.equals(p._2);\n");
sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "return false;\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
// hashCode
sb.append(ind(2) + "public int hashCode() {\n");
sb.append(ind(3) + "return 31*_1.hashCode() + _2.hashCode();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
}
aspect NameResolutionHelper {
public String Program.generateRewriteToSuperTypeStub() {
StringBuilder sb = new StringBuilder();
generateRewriteToSuperTypeStub(sb);
return sb.toString();
}
public String Program.generateResolverStubs() {
StringBuilder sb = new StringBuilder();
generateResolverStubs(sb);
return sb.toString();
}
public void Program.generateResolverStubs(StringBuilder sb) {
sb.append("aspect RefResolverStubs {\n\n");
for (Relation r: getRelations()) {
r.generateContextDependentNameResolution(sb);
}
if (resolverHelper || ASTNode.jsonPointer || ASTNode.manualReferences) {
for (TypeDecl decl : getTypeDeclList()) {
decl.generateContextIndependentNameResolution(sb);
sb.append("\n");
}
}
sb.append("}\n\n");
if (ASTNode.manualReferences) {
sb.append("aspect RefCreatorStubs {\n\n");
for (Relation r: getRelations()) {
r.generateContextDependentRefCreation(sb);
}
generateGenericRefCreation(sb);
sb.append("\n");
for (TypeDecl decl : getTypeDeclList()) {
decl.generateContextIndependentRefCreation(sb);
sb.append("\n");
}
sb.append("}\n\n");
}
}
public void Program.generateGenericRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// generic reference creation\n");
sb.append(ind(1) + "syn String ASTNode.createReference();\n");
sb.append(ind(1) + "eq ASTNode.createReference() {\n");
sb.append(ind(2) + "throw new RuntimeException(\"Generic reference creation not implemented.\");\n");
sb.append(ind(1) + "}\n");
}
public void Relation.generateContextDependentRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// " + prettyPrint() + "\n");
getDirection().generateContextDependentRefCreation(sb);
sb.append("\n");
}
public abstract void Direction.generateContextDependentRefCreation(StringBuilder sb);
public void RightDirection.generateContextDependentRefCreation(StringBuilder sb) {
relation().getLeft().generateContextDependentRefCreation(sb);
}
public void LeftDirection.generateContextDependentRefCreation(StringBuilder sb) {
relation().getRight().generateContextDependentRefCreation(sb);
}
public void Bidirectional.generateContextDependentRefCreation(StringBuilder sb) {
relation().getLeft().generateContextDependentRefCreation(sb);
relation().getRight().generateContextDependentRefCreation(sb);
}
public void RelationComponent.generateContextDependentRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// context-dependent reference creation\n");
sb.append(ind(1) + "syn String " + getTypeUse().decl() + ".createRefTo" + nameCapitalized() + "(" + ofTypeDecl() + " target) {\n");
sb.append(ind(2) + "// default to context-independent reference creation\n");
sb.append(ind(2) + "return target.createReference();\n");
sb.append(ind(1) + "}\n");
}
public void TypeDecl.generateContextIndependentRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// context-independent reference creation\n");
sb.append(ind(1) + "eq " + getID() + ".createReference() {\n");
sb.append(ind(2) + "// default to generic reference creation\n");
sb.append(ind(2) + "return super.createReference();\n");
sb.append(ind(1) + "}\n");
}
public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) {
sb.append("aspect ReferenceCreation {\n\n");
for (TypeDecl decl : getTypeDeclList()) {
decl.createReferenceCreator(sb);
}
sb.append("}\n\n");
sb.append("aspect ResolverTrigger {\n\n");
resolveAll(sb);
for (TypeDecl decl : getTypeDeclList()) {
decl.resolveAll(sb);
}
sb.append("}\n\n");
sb.append("aspect RefResolverHelpers {\n\n");
sb.append(ind(1) + "interface Unresolved$Node {\n");
sb.append(ind(2) + "String getUnresolved$Token();\n");
sb.append(ind(2) + "boolean getUnresolved$ResolveOpposite();\n");
sb.append(ind(1) + "}\n\n");
for (TypeDecl td: getTypeDecls()) {
if (td.needUnresolvedClass()) {
td.generateUnresolvedClass(sb);
}
}
sb.append("\n}\n");
}
public void TypeDecl.createReferenceCreator(StringBuilder sb) {
TypeDecl instantiableSubType = instantiableSubType();
if (instantiableSubType == null) {
throw new RuntimeException("unable to find instantiable subtype for " + getID());
}
sb.append(ind(1) + "public static " + getID() + " " + getID() + ".createRef(String ref) {\n");
sb.append(ind(2) + "Unresolved$" + instantiableSubType.getID() + " unresolvedNode = new Unresolved$" + instantiableSubType.getID() + "();\n");
sb.append(ind(2) + "unresolvedNode.setUnresolved$Token(ref);\n");
sb.append(ind(2) + "unresolvedNode.setUnresolved$ResolveOpposite(true);\n");
sb.append(ind(2) + "return unresolvedNode;\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public static " + getID() + " " + getID() + ".createRefDirection(String ref) {\n");
sb.append(ind(2) + "Unresolved$" + instantiableSubType.getID() + " unresolvedNode = new Unresolved$" + instantiableSubType.getID() + "();\n");
sb.append(ind(2) + "unresolvedNode.setUnresolved$Token(ref);\n");
sb.append(ind(2) + "unresolvedNode.setUnresolved$ResolveOpposite(false);\n");
sb.append(ind(2) + "return unresolvedNode;\n");
sb.append(ind(1) + "}\n");
}
public void TypeDecl.generateContextIndependentNameResolution(StringBuilder sb) {
sb.append(ind(1) + "// context-independent name resolution\n");
sb.append(ind(1) + "uncache ASTNode.globallyResolve" + getID() + "ByToken(String id);\n");
sb.append(ind(1) + "syn " + getID() + " ASTNode.globallyResolve" + getID() + "ByToken(String id) {\n");
if (serializer && !manualReferences) {
if (jsonPointer) {
sb.append(ind(2) + "return (" + getID() + ") resolveJsonPointer(id);\n");
} else {
sb.append(ind(2) + "return (" + getID() + ") globallyResolveASTNodeByUID(id);\n");
}
} else {
sb.append(ind(2) + "// perform context independent name resolution here using the id\n");
sb.append(ind(2) + "throw new RuntimeException(\"Context-independent name resolution for " + getID() + " not implemented.\");\n");
}
sb.append(ind(1) + "}\n");
}
public void Relation.generateContextDependentNameResolution(StringBuilder sb) {
sb.append(ind(1) + "// " + prettyPrint() + "\n");
getDirection().generateContextDependentNameResolution(sb);
sb.append("\n");
}
public abstract void Direction.generateContextDependentNameResolution(StringBuilder sb);
public void RightDirection.generateContextDependentNameResolution(StringBuilder sb) {
relation().getLeft().generateContextDependentNameResolution(sb);
}
public void LeftDirection.generateContextDependentNameResolution(StringBuilder sb) {
relation().getRight().generateContextDependentNameResolution(sb);
}
public void Bidirectional.generateContextDependentNameResolution(StringBuilder sb) {
relation().getLeft().generateContextDependentNameResolution(sb);
relation().getRight().generateContextDependentNameResolution(sb);
}
public abstract void RelationComponent.generateContextDependentNameResolution(StringBuilder sb);
public void OneRelationComponent.generateContextDependentNameResolution(StringBuilder sb) {
generateDirectedContextDependentNameResolution(sb);
}
public void OptionalRelationComponent.generateContextDependentNameResolution(StringBuilder sb) {
// optional relations are resolved in the same way as mandatory relations
// TODO maybe, there should be a check if the id to be solved is empty or null
generateDirectedContextDependentNameResolution(sb);
}
public void ManyRelationComponent.generateContextDependentNameResolution(StringBuilder sb) {
if (serializer && !resolverHelper) {
sb.append(ind(1) + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position) {\n");
sb.append(ind(2) + "return (" + ofTypeDecl() + ") globallyResolveASTNodeByUID(id);\n");
sb.append(ind(1) + "}\n");
} else {
sb.append(ind(1) + "// context-dependent name resolution\n");
sb.append(ind(1) + "uncache " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position);\n");
sb.append(ind(1) + "syn " + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id, int position) {\n");
sb.append(ind(2) + "// default to context-independent name resolution\n");
sb.append(ind(2) + "return globallyResolve" + ofTypeDecl() + "ByToken(id);\n");
sb.append(ind(1) + "}\n");
}
}
public void RelationComponent.generateDirectedContextDependentNameResolution(StringBuilder sb) {
if (serializer && !resolverHelper) {
sb.append(ind(1) + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id) {\n");
sb.append(ind(2) + "return (" + ofTypeDecl() + ") globallyResolveASTNodeByUID(id);\n");
sb.append(ind(1) + "}\n");
} else {
sb.append(ind(1) + "// context-dependent name resolution\n");
sb.append(ind(1) + "uncache " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id);\n");
sb.append(ind(1) + "syn " + ofTypeDecl() + " " + getTypeUse().decl() + ".resolve" + nameCapitalized() + "ByToken(String id) {\n");
sb.append(ind(2) + "// default to context-independent name resolution\n");
sb.append(ind(2) + "return globallyResolve" + ofTypeDecl() + "ByToken(id);\n");
sb.append(ind(1) + "}\n");
}
}
public void Program.resolveAll(StringBuilder sb) {
sb.append(ind(1) + "// enforce resolving of all non-containment relations of the current non-terminal\n");
sb.append(ind(1) + "public void ASTNode.resolveAll() {\n");
sb.append(ind(1) + "}\n\n");
sb.append(ind(1) + "// enforce resolving in the entire subtree\n");
sb.append(ind(1) + "public void ASTNode.treeResolveAll() {\n");
sb.append(ind(2) + "if (children != null) {\n");
sb.append(ind(3) + "for (int i = 0; i < numChildren; ++i) {\n");
sb.append(ind(4) + "ASTNode child = children[i];\n");
sb.append(ind(4) + "if (child != null) {\n");
sb.append(ind(5) + "child.treeResolveAll();\n");
sb.append(ind(4) + "}\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "resolveAll();\n");
sb.append(ind(1) + "}\n");
}
public void TypeDecl.resolveAll(StringBuilder sb) {
sb.append(ind(1) + "// enforce resolving of all non-containment relations of the current non-terminal\n");
sb.append(ind(1) + "public void " + getID() + ".resolveAll() {\n");
for (RelationComponent relationComponent : relationComponents()) {
sb.append(ind(2));
if (useJastAddNames) {
sb.append("get" + relationComponent.nameCapitalized());
} else {
sb.append(relationComponent.name());
}
sb.append(relationComponent.isMany() && useJastAddNames ? "List" : "").append("();\n");
}
sb.append(ind(2) + "super.resolveAll();\n");
sb.append(ind(1) + "}\n");
}
}
aspect PrettyPrinting {
public String Relation.prettyPrint() {
return "rel "
+ getLeft().prettyPrint() + " "
+ getDirection().prettyPrint() + " "
+ getRight().prettyPrint();
}
public String RelationComponent.prettyPrint() {
if (getID().isEmpty()) {
return getTypeUse().toString();
} else {
return getTypeUse() + "." + getID();
}
}
public String OptionalRelationComponent.prettyPrint() {
return super.prettyPrint() + "?";
}
public String ManyRelationComponent.prettyPrint() {
return super.prettyPrint() + "*";
}
abstract public String Direction.prettyPrint();
public String RightDirection.prettyPrint() {
return "->";
}
public String LeftDirection.prettyPrint() {
return "<-";
}
public String Bidirectional.prettyPrint() {
return "<->";
}
}
aspect Utils {
public String ASTNode.ind(int n) {
String s = "";
for (int i = 0; i < n; i++) {
s += " ";
}
return s;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment