mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-13 22:16:11 +00:00
Added annotations as definitive children of nodes in our custom AST, and updated the visitor to call a separate visitAnnotationOnX method for annotated stuff. This way, 'handled' can be set per annotation.
Also fixed a bug in AST generation that caused StackOverflowErrors on most source files, and did some cosmetic renaming of parameters.
This commit is contained in:
1 parent
12ff7ca223
commit
c2fd0a1ef5
4 files changed
+83
-37
No files matched your search
@@ -17,6 +17,7 @@ import org.eclipse.jdt.internal.compiler.CompilationResult;
|
||||
import org.eclipse.jdt.internal.compiler.apt.dispatch.AptProblem;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Clinit;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
@@ -60,6 +61,16 @@ public class EclipseAST {
|
||||
visitor.visitLocal(child, (LocalDeclaration)n);
|
||||
traverseChildren(visitor, child);
|
||||
visitor.endVisitLocal(child, (LocalDeclaration)n);
|
||||
} else if ( n instanceof Annotation ) {
|
||||
Node parent = child.up();
|
||||
if ( parent.node instanceof TypeDeclaration )
|
||||
visitor.visitAnnotationOnType(parent, (TypeDeclaration)parent.node, (Annotation)n);
|
||||
else if ( parent.node instanceof AbstractMethodDeclaration )
|
||||
visitor.visitAnnotationOnMethod(parent, (AbstractMethodDeclaration)parent.node, (Annotation)n);
|
||||
else if ( parent.node instanceof FieldDeclaration )
|
||||
visitor.visitAnnotationOnField(parent, (FieldDeclaration)parent.node, (Annotation)n);
|
||||
else if ( parent.node instanceof LocalDeclaration )
|
||||
visitor.visitAnnotationOnLocal(parent, (LocalDeclaration)parent.node, (Annotation)n);
|
||||
} else if ( n instanceof Statement ) {
|
||||
visitor.visitStatement(child, (Statement)n);
|
||||
traverseChildren(visitor, child);
|
||||
@@ -302,6 +313,7 @@ public class EclipseAST {
|
||||
childNodes.addAll(buildTree(type.fields));
|
||||
childNodes.addAll(buildTree(type.memberTypes));
|
||||
childNodes.addAll(buildTree(type.methods));
|
||||
childNodes.addAll(buildTree(type.annotations));
|
||||
return putInMap(new Node(type, childNodes));
|
||||
}
|
||||
|
||||
@@ -320,7 +332,10 @@ public class EclipseAST {
|
||||
private Node buildTree(FieldDeclaration field) {
|
||||
if ( field instanceof Initializer ) return buildTree((Initializer)field);
|
||||
if ( identityDetector.containsKey(field) ) return null;
|
||||
return putInMap(new Node(field, singleton(buildWithStatement(field.initialization))));
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
addIfNotNull(childNodes, buildWithStatement(field.initialization));
|
||||
childNodes.addAll(buildTree(field.annotations));
|
||||
return putInMap(new Node(field, childNodes));
|
||||
}
|
||||
|
||||
private Node buildTree(Initializer initializer) {
|
||||
@@ -340,6 +355,7 @@ public class EclipseAST {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
childNodes.addAll(buildTree(method.arguments));
|
||||
childNodes.addAll(buildTree(method.statements));
|
||||
childNodes.addAll(buildTree(method.annotations));
|
||||
return putInMap(new Node(method, childNodes));
|
||||
}
|
||||
|
||||
@@ -355,7 +371,20 @@ public class EclipseAST {
|
||||
|
||||
private Node buildTree(LocalDeclaration local) {
|
||||
if ( identityDetector.containsKey(local) ) return null;
|
||||
return putInMap(new Node(local, singleton(buildWithStatement(local.initialization))));
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
addIfNotNull(childNodes, buildWithStatement(local.initialization));
|
||||
childNodes.addAll(buildTree(local.annotations));
|
||||
return putInMap(new Node(local, childNodes));
|
||||
}
|
||||
|
||||
private Collection<Node> buildTree(Annotation[] annotations) {
|
||||
if ( annotations == null ) return Collections.emptyList();
|
||||
List<Node> elements = new ArrayList<Node>();
|
||||
for ( Annotation an : annotations ) {
|
||||
if ( an == null ) continue;
|
||||
elements.add(putInMap(new Node(an, null)));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
private Collection<Node> buildTree(Statement[] children) {
|
||||
@@ -375,13 +404,14 @@ public class EclipseAST {
|
||||
//We drill down because LocalDeclarations and TypeDeclarations can occur anywhere, even in, say,
|
||||
//an if block, or even the expression on an assert statement!
|
||||
|
||||
identityDetector.put(child, null);
|
||||
return drill(child);
|
||||
}
|
||||
|
||||
private Node drill(Statement statement) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( FieldAccess fa : fieldsOf(statement.getClass()) ) childNodes.addAll(buildWithField(statement, fa));
|
||||
return new Node(statement, childNodes);
|
||||
return putInMap(new Node(statement, childNodes));
|
||||
}
|
||||
|
||||
private static class FieldAccess {
|
||||
|
||||
@@ -3,6 +3,7 @@ package lombok.eclipse;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Initializer;
|
||||
@@ -14,14 +15,18 @@ public abstract class EclipseASTAdapter implements EclipseASTVisitor {
|
||||
@Override public void visitCompilationUnit(Node node, CompilationUnitDeclaration unit) {}
|
||||
@Override public void endVisitCompilationUnit(Node node, CompilationUnitDeclaration unit) {}
|
||||
@Override public void visitType(Node node, TypeDeclaration type) {}
|
||||
@Override public void visitAnnotationOnType(Node node, TypeDeclaration type, Annotation annotation) {}
|
||||
@Override public void endVisitType(Node node, TypeDeclaration type) {}
|
||||
@Override public void visitInitializer(Node node, Initializer initializer) {}
|
||||
@Override public void endVisitInitializer(Node node, Initializer initializer) {}
|
||||
@Override public void visitField(Node node, FieldDeclaration field) {}
|
||||
@Override public void visitAnnotationOnField(Node node, FieldDeclaration Field, Annotation annotation) {}
|
||||
@Override public void endVisitField(Node node, FieldDeclaration field) {}
|
||||
@Override public void visitMethod(Node node, AbstractMethodDeclaration method) {}
|
||||
@Override public void visitAnnotationOnMethod(Node node, AbstractMethodDeclaration method, Annotation annotation) {}
|
||||
@Override public void endVisitMethod(Node node, AbstractMethodDeclaration method) {}
|
||||
@Override public void visitLocal(Node node, LocalDeclaration local) {}
|
||||
@Override public void visitAnnotationOnLocal(Node node, LocalDeclaration local, Annotation annotation) {}
|
||||
@Override public void endVisitLocal(Node node, LocalDeclaration local) {}
|
||||
@Override public void visitStatement(Node node, Statement statement) {}
|
||||
@Override public void endVisitStatement(Node node, Statement statement) {}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.lang.reflect.Modifier;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Block;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
@@ -16,18 +17,20 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
|
||||
|
||||
//TODO
|
||||
public interface EclipseASTVisitor {
|
||||
/**
|
||||
* Called at the very beginning and end.
|
||||
*/
|
||||
void visitCompilationUnit(Node node, CompilationUnitDeclaration unit);
|
||||
void endVisitCompilationUnit(Node node, CompilationUnitDeclaration unit);
|
||||
void visitCompilationUnit(Node top, CompilationUnitDeclaration unit);
|
||||
void endVisitCompilationUnit(Node top, CompilationUnitDeclaration unit);
|
||||
|
||||
/**
|
||||
* Called when visiting a type (a class, interface, annotation, enum, etcetera).
|
||||
*/
|
||||
void visitType(Node node, TypeDeclaration type);
|
||||
void endVisitType(Node node, TypeDeclaration type);
|
||||
void visitType(Node typeNode, TypeDeclaration type);
|
||||
void visitAnnotationOnType(Node typeNode, TypeDeclaration type, Annotation annotation);
|
||||
void endVisitType(Node typeNode, TypeDeclaration type);
|
||||
|
||||
/**
|
||||
* Called when visiting a field of a class.
|
||||
@@ -35,39 +38,42 @@ public interface EclipseASTVisitor {
|
||||
* which are a subclass of FieldDeclaration, those do NOT result in a call to this method. They result
|
||||
* in a call to the visitInitializer method.
|
||||
*/
|
||||
void visitField(Node node, FieldDeclaration field);
|
||||
void endVisitField(Node node, FieldDeclaration field);
|
||||
void visitField(Node fieldNode, FieldDeclaration field);
|
||||
void visitAnnotationOnField(Node fieldNode, FieldDeclaration Field, Annotation annotation);
|
||||
void endVisitField(Node fieldNode, FieldDeclaration field);
|
||||
|
||||
/**
|
||||
* Called for static and instance initializers. You can tell the difference via the modifier flag on the
|
||||
* ASTNode (8 for static, 0 for not static). The content is in the 'block', not in the 'initialization',
|
||||
* which would always be null for an initializer instance.
|
||||
*/
|
||||
void visitInitializer(Node node, Initializer initializer);
|
||||
void endVisitInitializer(Node node, Initializer initializer);
|
||||
void visitInitializer(Node initializerNode, Initializer initializer);
|
||||
void endVisitInitializer(Node initializerNode, Initializer initializer);
|
||||
|
||||
/**
|
||||
* Called for both methods (MethodDeclaration) and constructors (ConstructorDeclaration), but not for
|
||||
* Clinit objects, which are a vestigial eclipse thing that never contain anything. Static initializers
|
||||
* show up as 'Initializer', in the visitInitializer method, with modifier bit STATIC set.
|
||||
*/
|
||||
void visitMethod(Node node, AbstractMethodDeclaration declaration);
|
||||
void endVisitMethod(Node node, AbstractMethodDeclaration declaration);
|
||||
void visitMethod(Node methodNode, AbstractMethodDeclaration method);
|
||||
void visitAnnotationOnMethod(Node methodNode, AbstractMethodDeclaration method, Annotation annotation);
|
||||
void endVisitMethod(Node methodNode, AbstractMethodDeclaration method);
|
||||
|
||||
/**
|
||||
* Visits a local declaration - that is, something like 'int x = 10;' on the method level. Also called
|
||||
* for method parameter (those would be Arguments, a subclass of LocalDeclaration).
|
||||
*/
|
||||
void visitLocal(Node node, LocalDeclaration declaration);
|
||||
void endVisitLocal(Node node, LocalDeclaration declaration);
|
||||
void visitLocal(Node localNode, LocalDeclaration local);
|
||||
void visitAnnotationOnLocal(Node localNode, LocalDeclaration local, Annotation annotation);
|
||||
void endVisitLocal(Node localNode, LocalDeclaration local);
|
||||
|
||||
/**
|
||||
* Visits a statement that isn't any of the other visit methods (e.g. TypeDeclaration).
|
||||
* @param node
|
||||
* @param statement
|
||||
*/
|
||||
void visitStatement(Node node, Statement statement);
|
||||
void endVisitStatement(Node node, Statement statement);
|
||||
void visitStatement(Node statementNode, Statement statement);
|
||||
void endVisitStatement(Node statementNode, Statement statement);
|
||||
|
||||
public static class EclipseASTPrinter implements EclipseASTVisitor {
|
||||
int indent = 0;
|
||||
@@ -112,6 +118,10 @@ public interface EclipseASTVisitor {
|
||||
indent++;
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnType(Node node, TypeDeclaration type, Annotation annotation) {
|
||||
print("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitType(Node node, TypeDeclaration type) {
|
||||
indent--;
|
||||
print("</TYPE %s>", str(type.name));
|
||||
@@ -136,6 +146,10 @@ public interface EclipseASTVisitor {
|
||||
indent++;
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnField(Node node, FieldDeclaration field, Annotation annotation) {
|
||||
print("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitField(Node node, FieldDeclaration field) {
|
||||
indent--;
|
||||
print("</FIELD %s %s>", str(field.type), str(field.name));
|
||||
@@ -147,6 +161,10 @@ public interface EclipseASTVisitor {
|
||||
indent++;
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethod(Node node, AbstractMethodDeclaration method, Annotation annotation) {
|
||||
print("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitMethod(Node node, AbstractMethodDeclaration method) {
|
||||
String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD";
|
||||
indent--;
|
||||
@@ -159,6 +177,10 @@ public interface EclipseASTVisitor {
|
||||
indent++;
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnLocal(Node node, LocalDeclaration local, Annotation annotation) {
|
||||
print("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitLocal(Node node, LocalDeclaration local) {
|
||||
String type = local instanceof Argument ? "ARGUMENT" : "LOCAL";
|
||||
indent--;
|
||||
|
||||
@@ -107,36 +107,25 @@ public class TransformEclipseAST {
|
||||
}
|
||||
|
||||
public void go() {
|
||||
// if ( ast.getFileName().contains("Foo") ) ast.traverse(new EclipseASTVisitor.EclipseASTPrinter());
|
||||
ast.traverse(new AnnotationVisitor());
|
||||
}
|
||||
|
||||
private static class AnnotationVisitor extends EclipseASTAdapter {
|
||||
@Override public void visitField(Node node, FieldDeclaration field) {
|
||||
if ( field.annotations == null ) return;
|
||||
for ( Annotation annotation : field.annotations ) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
@Override public void visitAnnotationOnField(Node node, FieldDeclaration field, Annotation annotation) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
|
||||
@Override public void visitLocal(Node node, LocalDeclaration local) {
|
||||
if ( local.annotations == null ) return;
|
||||
for ( Annotation annotation : local.annotations ) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
@Override public void visitAnnotationOnLocal(Node node, LocalDeclaration local, Annotation annotation) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
|
||||
@Override public void visitMethod(Node node, AbstractMethodDeclaration method) {
|
||||
if ( method.annotations == null ) return;
|
||||
for ( Annotation annotation : method.annotations ) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
@Override public void visitAnnotationOnMethod(Node node, AbstractMethodDeclaration method, Annotation annotation) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
|
||||
@Override public void visitType(Node node, TypeDeclaration type) {
|
||||
if ( type.annotations == null ) return;
|
||||
for ( Annotation annotation : type.annotations ) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
@Override public void visitAnnotationOnType(Node node, TypeDeclaration type, Annotation annotation) {
|
||||
handlers.handle((CompilationUnitDeclaration) node.top().node, node, annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user