Skip to content
Snippets Groups Projects

1.2.2

Merged René Schöne requested to merge dev into main
7 files
+ 363
352
Compare changes
  • Side-by-side
  • Inline
Files
7
+ 179
0
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);
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 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();
}
Loading