Commit fd6946d8 authored by Johannes Mey's avatar Johannes Mey Committed by René Schöne
Browse files

Implement JSON pointer (built-in) and manual pointer treatment with two...

Implement JSON pointer (built-in) and manual pointer treatment with two examples (JSON pointer and relative JSON pointer)
parent 6a3f2671
Pipeline #5096 passed with stage
in 2 minutes and 3 seconds
# RelAST Preprocessor Version 0.2.3
# RelAST Preprocessor Version 0.2.4
![RelAST process](relast-process.png)
......
......@@ -246,6 +246,95 @@ task compileSerializerDefaultNamesTest(type: RelastTest) {
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileSerializerPointerTest(type: RelastTest) {
verbose = true
resolverHelper = true
relastFiles 'src/test/jastadd/serializer-pointer/Serializer.relast'
grammarName = 'src/test/jastadd/serializer-pointer/Serializer'
serializer = 'jackson-json-pointer'
packageName = 'pointer.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileSerializerManualTest(type: RelastTest) {
verbose = true
resolverHelper = true
relastFiles 'src/test/jastadd/serializer-manual/Serializer.relast'
grammarName = 'src/test/jastadd/serializer-manual/Serializer'
serializer = 'jackson-manual-references'
packageName = 'manual.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/serializer-manual/JsonPointer.jrag'
}
task compileSerializerManualRelativeTest(type: RelastTest) {
verbose = true
resolverHelper = true
relastFiles 'src/test/jastadd/serializer-manual-relative/Serializer.relast'
grammarName = 'src/test/jastadd/serializer-manual-relative/Serializer'
serializer = 'jackson-manual-references'
packageName = 'manual.relative.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/serializer-manual-relative/JsonPointer.jrag'
}
clean {
delete 'src/test/jastadd/serializer-names/Serializer.ast'
delete 'src/test/jastadd/serializer-names/Serializer.jadd'
delete 'src/test/jastadd/serializer-names/SerializerSerializer.jadd'
delete 'src/test/jastadd/serializer-names/SerializerResolverStubs.jrag'
delete 'src/test/jastadd/serializer-names/SerializerRefResolver.jadd'
delete 'src/test/jastadd/serializer-manual/Serializer.ast'
delete 'src/test/jastadd/serializer-manual/Serializer.jadd'
delete 'src/test/jastadd/serializer-manual/SerializerSerializer.jadd'
delete 'src/test/jastadd/serializer-manual/SerializerResolverStubs.jrag'
delete 'src/test/jastadd/serializer-manual/SerializerRefResolver.jadd'
delete 'src/test/jastadd/resolver2/Resolver.jadd'
delete 'src/test/jastadd/resolver2/Resolver.ast'
delete 'src/test/jastadd/resolver2/ResolverRefResolver.jadd'
delete 'src/test/jastadd/resolver2/ResolverResolverStubs.jrag'
delete 'src/test/jastadd/serializer-manual-relative/Serializer.ast'
delete 'src/test/jastadd/serializer-manual-relative/Serializer.jadd'
delete 'src/test/jastadd/serializer-manual-relative/SerializerSerializer.jadd'
delete 'src/test/jastadd/serializer-manual-relative/SerializerResolverStubs.jrag'
delete 'src/test/jastadd/serializer-manual-relative/SerializerRefResolver.jadd'
delete 'src/test/jastadd/serializer-pointer/Serializer.ast'
delete 'src/test/jastadd/serializer-pointer/Serializer.jadd'
delete 'src/test/jastadd/serializer-pointer/SerializerSerializer.jadd'
delete 'src/test/jastadd/serializer-pointer/SerializerResolverStubs.jrag'
delete 'src/test/jastadd/serializer-pointer/SerializerRefResolver.jadd'
delete 'src/test/jastadd/lowerbounds/LowerBounds.jadd'
delete 'src/test/jastadd/lowerbounds/LowerBounds.ast'
delete 'src/test/jastadd/resolver/Resolver.jadd'
delete 'src/test/jastadd/resolver/Resolver.ast'
delete 'src/test/jastadd/resolver/Resolver2.jadd'
delete 'src/test/jastadd/resolver/Resolver2.ast'
delete 'src/test/jastadd/resolver/Resolver2ResolverStubs.jrag'
delete 'src/test/jastadd/resolver/ResolverRefResolver.jadd'
delete 'src/test/jastadd/resolver/ResolverResolverStubs.jrag'
delete 'src/test/jastadd/resolver/Resolver2RefResolver.jadd'
delete 'src/test/jastadd/errors/Errors.out'
delete 'src/test/jastadd/errors/Inheritance.out'
delete 'src/test/jastadd/errors/Multiple.out'
delete 'src/test/jastadd/errors/InheritanceLeft.out'
delete 'src/test/jastadd/errors/ErrorsLeft.out'
delete 'src/test/jastadd/errors/MultipleLeft.out'
delete 'src/test/jastadd/serializer/Serializer.ast'
delete 'src/test/jastadd/serializer/Serializer.jadd'
delete 'src/test/jastadd/serializer/SerializerSerializer.jadd'
delete 'src/test/jastadd/serializer/SerializerResolverStubs.jrag'
delete 'src/test/jastadd/serializer/SerializerRefResolver.jadd'
delete 'src/test/jastadd/listnames/ListNames.jadd'
delete 'src/test/jastadd/listnames/ListNames.ast'
delete 'src/test/jastadd/relations/Relations2.jadd'
delete 'src/test/jastadd/relations/Relations3.ast'
delete 'src/test/jastadd/relations/Relations2.ast'
delete 'src/test/jastadd/relations/Relations.ast'
delete 'src/test/jastadd/relations/Relations.jadd'
delete 'src/test/jastadd/relations/Relations3.jadd'
delete 'src/test/jastadd/multiple/Multiple.jadd'
delete 'src/test/jastadd/multiple/Multiple.ast'
}
test {
outputs.upToDateWhen { false }
useJUnitPlatform()
......
......@@ -5,6 +5,8 @@ aspect BackendAbstractGrammar {
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() {
......@@ -823,13 +825,73 @@ aspect NameResolutionHelper {
r.generateContextDependentNameResolution(sb);
}
if (resolverHelper) {
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) {
......@@ -894,8 +956,12 @@ aspect NameResolutionHelper {
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) {
sb.append(ind(2) + "return (" + getID() + ") globallyResolveASTNodeByUID(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");
......@@ -1002,11 +1068,18 @@ aspect Serializer {
protected static String ASTNode.jsonTypeKey = "type";
protected static String ASTNode.jsonNodeType = "com.fasterxml.jackson.databind.JsonNode";
protected static String ASTNode.jsonNodeTypeAccessor = ".get(\"" + jsonTypeKey + "\").asText()";
public String Program.generateSerializer() {
public String Program.generateJacksonSerializer() {
StringBuilder sb = new StringBuilder();
generateFromJson(sb);
generateToJson(sb);
writeUID(sb);
if (jsonPointer) {
writeJsonPointer(sb);
} else if (manualReferences) {
// TODO
} else {
writeUID(sb);
}
return sb.toString();
}
......@@ -1083,9 +1156,11 @@ aspect Serializer {
sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "g.writeObjectFieldStart(fieldName);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "g.writeStringField(\"" + jsonTypeKey + "\", \"" + getID() + "\");\n");
sb.append(ind(3) + "if (unique$Id() == null) throw new SerializationException(\"The unique identifier of " + getID() + " is missing.\");\n");
sb.append(ind(3) + "g.writeStringField(\"id\", unique$Id());\n");
if (!jsonPointer && !manualReferences) {
sb.append(ind(3) + "g.writeStringField(\"" + jsonTypeKey + "\", \"" + getID() + "\");\n");
sb.append(ind(3) + "if (unique$Id() == null) throw new SerializationException(\"The unique identifier of " + getID() + " is missing.\");\n");
sb.append(ind(3) + "g.writeStringField(\"id\", unique$Id());\n");
}
if (componentsTransitive().size() > 0) {
sb.append(ind(3) + "g.writeObjectFieldStart(\"children\");\n");
for (Component child : componentsTransitive()) {
......@@ -1196,18 +1271,42 @@ aspect Serializer {
public void OneRelationComponent.serialize(StringBuilder sb, int indent) {
if (useJastAddNames){
sb.append(ind(indent) + "g.writeStringField(\""+getID()+"\", get" + getID() + "().unique$Id());\n");
if (jsonPointer) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", createRefTo" + getID() + "(" + getID() + "()));\n");
} else {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n");
}
} else {
sb.append(ind(indent) + "g.writeStringField(\""+getID()+"\", " + getID() + "().unique$Id());\n");
if (jsonPointer) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", createRefTo" + getID() + "(" + getID() + "()));\n");
} else {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
}
}
}
public void OptionalRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (has" + nameCapitalized() + "()) {\n");
if (useJastAddNames){
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n");
if (jsonPointer) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().createReference());\n");
} else {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n");
}
} else {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
if (jsonPointer) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + "createRefTo" + getID() + "(" + getID() + "()));\n");
} else {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
}
}
sb.append(ind(indent) + "}\n");
}
......@@ -1219,7 +1318,14 @@ aspect Serializer {
} else {
sb.append(ind(indent) + "for (" + ofTypeDecl().getID() + " child : " + getID() + "()) {\n");
}
sb.append(ind(indent + 1) + "g.writeString(child.unique$Id());\n");
if (jsonPointer) {
sb.append(ind(indent + 1) + "g.writeString(child.jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent + 1) + "g.writeString(createRefTo" + getID() + "(child));\n");
}else {
sb.append(ind(indent + 1) + "g.writeString(child.unique$Id());\n");
}
sb.append(ind(indent) + "}\n");
sb.append(ind(indent) + "g.writeEndArray();\n");
}
......@@ -1256,10 +1362,12 @@ aspect Serializer {
sb.append(ind(2) + "element = new " + getID() + "();\n");
}
// deserialize id
sb.append(ind(2) + "if (node.has(\"id\")) {\n");
sb.append(ind(3) + "element.unique$Id = node.get(\"id\").asText();\n");
sb.append(ind(2) + "}\n");
if (!jsonPointer && !manualReferences) {
// deserialize id
sb.append(ind(2) + "if (node.has(\"id\")) {\n");
sb.append(ind(3) + "element.unique$Id = node.get(\"id\").asText();\n");
sb.append(ind(2) + "}\n");
}
// deserialize containment children
if (componentsTransitive().size() > 0) {
......@@ -1361,6 +1469,140 @@ aspect Serializer {
}
}
public void Component.writeJsonPointer(StringBuilder sb) {
// do nothing for other components
}
public void NormalComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void ListComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "(int index).jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "/\" + index;\n");
sb.append(ind(1) + "}\n");
}
public void OptComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void NTAComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void NTAListComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "(int index).jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "/\" + index;\n");
sb.append(ind(1) + "}\n");
}
public void NTAOptComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void Component.resolveJsonPointer(StringBuilder sb) {
// do nothing for other components
}
public void NormalComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void ListComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);\n");
}
public void OptComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void NTAComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void NTAListComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);\n");
}
public void NTAOptComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void TypeDecl.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + getID() + ".resolveJsonPointer(String[] pointer, int index) {\n");
sb.append(ind(2) + "if (pointer.length == 0 || pointer.length == index) {\n");
sb.append(ind(3) + "return this;\n");
sb.append(ind(2) + "} else if (pointer.length == index + 1) {\n");
sb.append(ind(3) + "throw new RuntimeException(\"there is only one child called \" + pointer[index]);\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "switch (pointer[index + 1]) {\n");
for (Component c: getComponentList()) {
c.resolveJsonPointer(sb);
}
sb.append(ind(4) + "default:\n");
sb.append(ind(5) + "return super.resolveJsonPointer(pointer, index);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void Program.writeJsonPointer(StringBuilder sb) {
sb.append("aspect JsonPointer {\n");
sb.append(ind(1) + "syn String ASTNode.jsonPointer() {\n");
sb.append(ind(2) + "if (getParent() == null) {\n");
sb.append(ind(3) + "return \"\";\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "return jsonPointerInh();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "inh String ASTNode.jsonPointerInh();\n");
// define json pointer for each component
for (TypeDecl td: getTypeDeclList()) {
for (Component c: td.getComponentList()) {
c.writeJsonPointer(sb);
}
}
sb.append(ind(1) + "syn ASTNode ASTNode.resolveJsonPointer(String pointer) = root().resolveJsonPointer(pointer.split(\"/\"), 1);\n");
sb.append(ind(1) + "ASTNode ASTNode.root() {\n");
sb.append(ind(2) + "if (getParent() == null) return this;\n");
sb.append(ind(2) + "else return getParent().root();\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "syn ASTNode ASTNode.resolveJsonPointer(String[] pointer, int index) {\n");
sb.append(ind(2) + "if (index < pointer.length) {\n");
sb.append(ind(3) + "throw new RuntimeException(\"found wrong child \" + pointer[index + 1] + \" in class \" + this.getClass().getSimpleName());\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "throw new RuntimeException(\"Cannot resolve JSON pointer for class \" + this.getClass().getSimpleName());\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
// resolve JSON pointers in each nonterminal
for (TypeDecl td: getTypeDeclList()) {
td.resolveJsonPointer(sb);
}
sb.append("}\n");
}
public void Program.writeUID(StringBuilder sb) {
sb.append("aspect UID {\n");
sb.append(ind(1) + "class UIDProvider {\n");
......
......@@ -14,7 +14,7 @@ import java.util.List;
public class Compiler {
private static final String VERSION = "0.2.3";
private static final String VERSION = "0.2.4";
private ArrayList<Option<?>> options;
private FlagOption optionWriteToFile;
......@@ -89,8 +89,17 @@ public class Compiler {
ASTNode.serializer = true;
switch (optionSerializer.getValue()) {
case "jackson":
writeToFile(grammarName + "Serializer.jadd", p.generateSerializer());
writeToFile(grammarName + "Serializer.jadd", p.generateJacksonSerializer());
break;
case "jackson-json-pointer":
ASTNode.jsonPointer = true;
writeToFile(grammarName + "Serializer.jadd", p.generateJacksonSerializer());
break;
case "jackson-manual-references":
ASTNode.manualReferences = true;
writeToFile(grammarName + "Serializer.jadd", p.generateJacksonSerializer());
break;
}
}
......@@ -151,7 +160,7 @@ public class Compiler {
optionResolverHelper = addOption(new FlagOption("resolverHelper", "create a subtype for each type containing a string that can be used to resolve the type later"));
optionJastAddList = addOption(new StringOption("jastAddList", "set the name of the List type in JastAdd (has to match the option '--List' or its default List)"));
optionUseJastaddNames = addOption(new FlagOption("useJastAddNames", "generate names in the form of addX, removeX and setX. If omitted, the default, original naming scheme resulting in addToX, removeFromX and setX will be used."));
optionSerializer = addOption(new EnumOption("serializer", "generate a (de-)serializer", Arrays.asList("jackson"), "jackson"));
optionSerializer = addOption(new EnumOption("serializer", "generate a (de-)serializer", Arrays.asList("jackson", "jackson-json-pointer", "jackson-manual-references"), "jackson"));
optionQuiet = addOption(new FlagOption("quiet", "do not output anything on stdout"));
}
......
aspect MyRewrites {
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveNamedElementByToken(String id) {
System.out.println("resolving " + id + " to " + root().findNamedElement(id));
return root().findNamedElement(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveAByToken(String id) {
System.out.println("resolving " + id + " to " + root().findNamedElement(id));
return root().findA(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveBByToken(String id) {
System.out.println("resolving " + id + " to " + root().findNamedElement(id));
return root().findB(id);
}
refine RefResolverStubs eq ASTNode.globallyResolveNamedElementByToken(String id) = root().findNamedElement(id);
refine RefResolverStubs eq ASTNode.globallyResolveAByToken(String id) = root().findA(id);
refine RefResolverStubs eq ASTNode.globallyResolveBByToken(String id) = root().findB(id);
}
aspect Utils {
inh Root ASTNode.root();
eq Root.getA(int i).root() = this;
eq Root.getB(int i).root() = this;
eq Root.getChild().root() = this;
syn NamedElement Root.findNamedElement(String name) {
for (A a : getAList()) {
......@@ -35,4 +34,4 @@ aspect Utils {
}
return null;
}
}
\ No newline at end of file
}
aspect Utils {
inh Root ASTNode.root();
eq Root.getA(int i).root() = this;
eq Root.getB(int i).root() = this;
eq Root.getChild().root() = this;
syn NamedElement Root.findNamedElement(String name) {
for (A a : getAList()) {
......@@ -35,4 +34,4 @@ aspect Utils {
}
return null;
}
}
\ No newline at end of file
}
aspect JsonPointer {
refine RefCreatorStubs eq A.createRefToDi1(B target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToDi2(B target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToDi3(B target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi1(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi1(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi2(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi2(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi3(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi3(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi5(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi5(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi6(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi6(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi9(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi9(A target) = createReferenceTo(target);
refine RefCreatorStubs eq Root.createRefToD(D target) = createReferenceTo(target);
refine RefCreatorStubs eq D.createRefToRoot(Root target) = createReferenceTo(target);
syn String ASTNode.createReferenceTo(ASTNode target) {
// find common subtree
java.util.List<ASTNode> myParents = parents();
java.util.List<ASTNode> targetParents = target.parents();
int minSize = Math.min(myParents.size(), targetParents.size());
if (minSize > 0) {
int commonDepth = 0;
while (commonDepth < minSize && myParents.get(commonDepth) == targetParents.get(commonDepth)) {
commonDepth ++;
}
int stepsUp = 0;
for (int i = commonDepth; i < myParents.size(); i++) {
stepsUp += (myParents.get(i).inList()) ? 3 : 2;
}
return stepsUp + "#" + target.jsonPointerFrom(myParents.get(commonDepth-1));
} else {
return (myParents.size() == 0) ? target.jsonPointerFrom(this) : myParents.size() + "#";
}
}
syn boolean ASTNode.inList() = (getParent() == null) ? false : inListInh();
inh boolean ASTNode.inListInh();
eq Root.getA().inListInh() = true;
eq Root.getB().inListInh() = true;
eq Root.getC().inListInh() = false;
eq C.getD1().inListInh() = false;
eq C.getD2().inListInh() = false;
eq C.getD3().inListInh() = true;
syn ASTNode ASTNode.goUp(int steps) = steps > 0 ? goUpInh(steps) : this;
inh ASTNode ASTNode.goUpInh(int steps);
eq Root.getA().goUpInh(int steps) = goUp(steps-3);
eq Root.getB().goUpInh(int steps) = goUp(steps-3);
eq Root.getC().goUpInh(int steps) = goUp(steps-2);
eq C.getD1().goUpInh(int steps) = goUp(steps-2);
eq C.getD2().goUpInh(int steps) = goUp(steps-2);
eq C.getD3().goUpInh(int steps) = goUp(steps-3);
/**
* return the parent from root to the current node
*/
syn java.util.List<ASTNode> ASTNode.parents() {
java.util.List<ASTNode> result = new java.util.ArrayList<>();
if (getParent() != null) {
result.addAll(getParent().parents());
if (!(this instanceof List) && !(this instanceof Opt)) result.add(this);
} else {
// add the root
result.add(this);
}
return result;