From 024d8ffa9801f463fecadd16f42d51bbed46dea7 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 17 Jun 2009 10:43:39 +0200 Subject: Massive refactors. This list isn't complete, but should give you an idea: A) many things in lombok.eclipse moved to lombok.core to enable reuse with lombok.javac. B) lombok.javac works now similarly to eclipse's model: We first make big ASTs that are bidirectionally traversable, then we walk through that for annotations. C) Instead of getting an annotation instance, you now get an object that is more flexible and can e.g. give you class values in an enum as a string instead of a Class object, which may fail if that class isn't on the classpath of lombok. D) sources to the internal sun classes for javac added to /contrib. --- src/lombok/eclipse/Eclipse.java | 10 + src/lombok/eclipse/EclipseAST.java | 370 +++++++++------------- src/lombok/eclipse/EclipseASTAdapter.java | 4 + src/lombok/eclipse/EclipseASTVisitor.java | 32 +- src/lombok/eclipse/EclipseAnnotationHandler.java | 4 +- src/lombok/eclipse/HandlerLibrary.java | 287 +++++------------ src/lombok/eclipse/TransformEclipseAST.java | 15 +- src/lombok/eclipse/TypeResolver.java | 100 ------ src/lombok/eclipse/handlers/HandleGetter_ecj.java | 11 +- 9 files changed, 296 insertions(+), 537 deletions(-) delete mode 100644 src/lombok/eclipse/TypeResolver.java (limited to 'src/lombok/eclipse') diff --git a/src/lombok/eclipse/Eclipse.java b/src/lombok/eclipse/Eclipse.java index e1ff95cd..961b9536 100644 --- a/src/lombok/eclipse/Eclipse.java +++ b/src/lombok/eclipse/Eclipse.java @@ -31,4 +31,14 @@ public class Eclipse { log.log(new Status(IStatus.ERROR, bundleName, message, error)); } + + static String toQualifiedName(char[][] typeName) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for ( char[] c : typeName ) { + sb.append(first ? "" : ".").append(c); + first = false; + } + return sb.toString(); + } } diff --git a/src/lombok/eclipse/EclipseAST.java b/src/lombok/eclipse/EclipseAST.java index 3fdd02e4..53a993ec 100644 --- a/src/lombok/eclipse/EclipseAST.java +++ b/src/lombok/eclipse/EclipseAST.java @@ -1,17 +1,13 @@ package lombok.eclipse; -import static lombok.Lombok.sneakyThrow; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import lombok.core.AST; + import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.apt.dispatch.AptProblem; @@ -22,24 +18,44 @@ import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Clinit; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.Util; -public class EclipseAST { +public class EclipseAST extends AST { + @Override public String getPackageDeclaration() { + CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().get(); + ImportReference pkg = cud.currentPackage; + return pkg == null ? null : Eclipse.toQualifiedName(pkg.getImportName()); + } + + @Override public Collection getImportStatements() { + List imports = new ArrayList(); + CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().get(); + if ( cud.imports == null ) return imports; + for ( ImportReference imp : cud.imports ) { + if ( imp == null ) continue; + imports.add(Eclipse.toQualifiedName(imp.getImportName())); + } + + return imports; + } + public void traverse(EclipseASTVisitor visitor) { Node current = top(); - visitor.visitCompilationUnit(current, (CompilationUnitDeclaration)current.node); + visitor.visitCompilationUnit(current, (CompilationUnitDeclaration)current.get()); traverseChildren(visitor, current); - visitor.endVisitCompilationUnit(current, (CompilationUnitDeclaration)current.node); + visitor.endVisitCompilationUnit(current, (CompilationUnitDeclaration)current.get()); } private void traverseChildren(EclipseASTVisitor visitor, Node node) { - for ( Node child : node.children ) { - ASTNode n = child.node; + for ( Node child : node.down() ) { + ASTNode n = child.get(); if ( n instanceof TypeDeclaration ) { visitor.visitType(child, (TypeDeclaration)n); traverseChildren(visitor, child); @@ -57,20 +73,33 @@ public class EclipseAST { visitor.visitMethod(child, (AbstractMethodDeclaration)n); traverseChildren(visitor, child); visitor.endVisitMethod(child, (AbstractMethodDeclaration)n); + } else if ( n instanceof Argument ) { + ASTNode parent = child.up().get(); + AbstractMethodDeclaration method = null; + if ( parent instanceof AbstractMethodDeclaration ) method = (AbstractMethodDeclaration)parent; + else System.out.println("Weird, this isn't a desc of method: " + parent.getClass() + ": " + parent); + visitor.visitMethodArgument(child, (Argument)n, method); + traverseChildren(visitor, child); + visitor.endVisitMethodArgument(child, (Argument)n, method); } else if ( n instanceof LocalDeclaration ) { 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((TypeDeclaration)parent.node, child, (Annotation)n); - else if ( parent.node instanceof AbstractMethodDeclaration ) - visitor.visitAnnotationOnMethod((AbstractMethodDeclaration)parent.node, child, (Annotation)n); - else if ( parent.node instanceof FieldDeclaration ) - visitor.visitAnnotationOnField((FieldDeclaration)parent.node, child, (Annotation)n); - else if ( parent.node instanceof LocalDeclaration ) - visitor.visitAnnotationOnLocal((LocalDeclaration)parent.node, child, (Annotation)n); + if ( parent.get() instanceof TypeDeclaration ) + visitor.visitAnnotationOnType((TypeDeclaration)parent.get(), child, (Annotation)n); + else if ( parent.get() instanceof AbstractMethodDeclaration ) + visitor.visitAnnotationOnMethod((AbstractMethodDeclaration)parent.get(), child, (Annotation)n); + else if ( parent.get() instanceof FieldDeclaration ) + visitor.visitAnnotationOnField((FieldDeclaration)parent.get(), child, (Annotation)n); + else if ( parent.get() instanceof Argument ) + visitor.visitAnnotationOnMethodArgument( + (Argument)parent.get(), + (AbstractMethodDeclaration)parent.directUp().get(), + child, (Annotation)n); + else if ( parent.get() instanceof LocalDeclaration ) + visitor.visitAnnotationOnLocal((LocalDeclaration)parent.get(), child, (Annotation)n); } else if ( n instanceof Statement ) { visitor.visitStatement(child, (Statement)n); traverseChildren(visitor, child); @@ -83,16 +112,12 @@ public class EclipseAST { return completeParse; } - public String getFileName() { - return fileName; - } - - public Node top() { - return top; + @Override public Node top() { + return (Node) super.top(); } public Node get(ASTNode node) { - return nodeMap.get(node); + return (Node) super.get(node); } private class ParseProblem { @@ -111,14 +136,14 @@ public class EclipseAST { } void addToCompilationResult() { - addProblemToCompilationResult(getFileName(), (CompilationUnitDeclaration) top().getEclipseNode(), - isWarning, message, node.getEclipseNode(), sourceStart, sourceEnd); + addProblemToCompilationResult(getFileName(), (CompilationUnitDeclaration) top().get(), + isWarning, message, node.get(), sourceStart, sourceEnd); } } - public void propagateProblems() { + private void propagateProblems() { if ( queuedProblems.isEmpty() ) return; - CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().getEclipseNode(); + CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().get(); if ( cud.compilationResult == null ) return; for ( ParseProblem problem : queuedProblems ) problem.addToCompilationResult(); queuedProblems.clear(); @@ -152,59 +177,44 @@ public class EclipseAST { ast.compilationResult.record(ecProblem, null); } - public final class Node { - final ASTNode node; - Node parent; - final Collection children; - boolean handled; - private final boolean isStructurallySignificant; + public final class Node extends AST.Node { + Node(ASTNode node, Collection children, Kind kind) { + super(node, children, kind); + } - Node(ASTNode node, Collection children) { - this.node = node; - this.children = children == null ? Collections.emptyList() : children; - this.isStructurallySignificant = calculateIsStructurallySignificant(); + @Override public String getName() { + final char[] n; + if ( node instanceof TypeDeclaration ) n = ((TypeDeclaration)node).name; + else if ( node instanceof FieldDeclaration ) n = ((FieldDeclaration)node).name; + else if ( node instanceof AbstractMethodDeclaration ) n = ((AbstractMethodDeclaration)node).selector; + else if ( node instanceof LocalDeclaration ) n = ((LocalDeclaration)node).name; + else n = null; + + return n == null ? null : new String(n); } - public void addError(String message) { - this.addError(message, this.getEclipseNode().sourceStart, this.getEclipseNode().sourceEnd); + @Override public void addError(String message) { + this.addError(message, this.get().sourceStart, this.get().sourceEnd); } public void addError(String message, int sourceStart, int sourceEnd) { addProblem(new ParseProblem(false, message, this, sourceStart, sourceEnd)); } - public void addWarning(String message) { - this.addWarning(message, this.getEclipseNode().sourceStart, this.getEclipseNode().sourceEnd); + @Override public void addWarning(String message) { + this.addWarning(message, this.get().sourceStart, this.get().sourceEnd); } public void addWarning(String message, int sourceStart, int sourceEnd) { addProblem(new ParseProblem(true, message, this, sourceStart, sourceEnd)); } - public ASTNode getEclipseNode() { - return node; - } - - /** Returns the structurally significant node that encloses this one. - * - * @see #isStructurallySignificant() - */ - public Node up() { - Node result = parent; - while ( result != null && !result.isStructurallySignificant() ) result = result.parent; - return result; - } - - /** - * Structurally significant means: LocalDeclaration, TypeDeclaration, MethodDeclaration, ConstructorDeclaration, - * FieldDeclaration, Initializer, and CompilationUnitDeclaration. - * The rest is e.g. if statements, while loops, etc. - */ - public boolean isStructurallySignificant() { - return isStructurallySignificant; + /** {@inheritDoc} */ + @Override public Node up() { + return (Node) super.up(); } - private boolean calculateIsStructurallySignificant() { + @Override protected boolean calculateIsStructurallySignificant() { if ( node instanceof TypeDeclaration ) return true; if ( node instanceof AbstractMethodDeclaration ) return true; if ( node instanceof FieldDeclaration ) return true; @@ -213,33 +223,20 @@ public class EclipseAST { return false; } - /** - * Returns the direct parent node in the AST tree of this node. For example, a local variable declaration's - * direct parent can be e.g. an If block, but its up() Node is the Method that contains it. - */ + /** {@inheritDoc} */ public Node directUp() { - return parent; - } - - public Collection down() { - return children; - } - - public boolean isHandled() { - return handled; + return (Node) super.directUp(); } - public Node setHandled() { - this.handled = true; - return this; + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public Collection down() { + return (Collection) children; } - public Node top() { - return top; - } - - public String getFileName() { - return fileName; + /** {@inheritDoc} */ + @Override public Node top() { + return (Node) super.top(); } public boolean isCompleteParse() { @@ -247,33 +244,33 @@ public class EclipseAST { } } - private final Map identityDetector = new IdentityHashMap(); - private Map nodeMap = new HashMap(); private final CompilationUnitDeclaration compilationUnitDeclaration; - private final String fileName; - private Node top; private boolean completeParse; public EclipseAST(CompilationUnitDeclaration ast) { + super(toFileName(ast)); this.compilationUnitDeclaration = ast; - this.fileName = ast.compilationResult.fileName == null ? "(unknown).java" : new String(ast.compilationResult.fileName); - this.top = buildTree(ast); + setTop(buildCompilationUnit(ast)); this.completeParse = isComplete(ast); } + private static String toFileName(CompilationUnitDeclaration ast) { + return ast.compilationResult.fileName == null ? null : new String(ast.compilationResult.fileName); + } + public void reparse() { propagateProblems(); if ( completeParse ) return; boolean newCompleteParse = isComplete(compilationUnitDeclaration); if ( !newCompleteParse ) return; - Map oldMap = nodeMap; - nodeMap = new HashMap(); - this.top = buildTree(compilationUnitDeclaration); + Map.Node> oldMap = getNodeMap(); + clearState(); + setTop(buildCompilationUnit(compilationUnitDeclaration)); //Retain 'handled' flags. - for ( Map.Entry e : nodeMap.entrySet() ) { - Node oldEntry = oldMap.get(e.getKey()); - if ( oldEntry != null && oldEntry.handled ) e.getValue().handled = true; + for ( Map.Entry.Node> e : getNodeMap().entrySet() ) { + Node oldEntry = (Node) oldMap.get(e.getKey()); + if ( oldEntry != null && oldEntry.isHandled() ) e.getValue().setHandled(); } this.completeParse = true; @@ -283,44 +280,36 @@ public class EclipseAST { return (unit.bits & ASTNode.HasAllMethodBodies) > 0; } - private Node putInMap(Node parent) { - for ( Node child : parent.children ) child.parent = parent; - nodeMap.put(parent.node, parent); - identityDetector.put(parent.node, null); - return parent; - } - - private Node buildTree(CompilationUnitDeclaration top) { - identityDetector.clear(); - Collection children = buildTree(top.types); - return putInMap(new Node(top, children)); + private Node buildCompilationUnit(CompilationUnitDeclaration top) { + Collection children = buildTypes(top.types); + return putInMap(new Node(top, children, Kind.COMPILATION_UNIT)); } private void addIfNotNull(Collection collection, Node n) { if ( n != null ) collection.add(n); } - private Collection buildTree(TypeDeclaration[] children) { + private Collection buildTypes(TypeDeclaration[] children) { if ( children == null ) return Collections.emptyList(); List childNodes = new ArrayList(); - for ( TypeDeclaration type : children ) addIfNotNull(childNodes, buildTree(type)); + for ( TypeDeclaration type : children ) addIfNotNull(childNodes, buildType(type)); return childNodes; } - private Node buildTree(TypeDeclaration type) { - if ( identityDetector.containsKey(type) ) return null; + private Node buildType(TypeDeclaration type) { + if ( alreadyHandled(type) ) return null; List childNodes = new ArrayList(); - 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)); + childNodes.addAll(buildFields(type.fields)); + childNodes.addAll(buildTypes(type.memberTypes)); + childNodes.addAll(buildMethods(type.methods)); + childNodes.addAll(buildAnnotations(type.annotations)); + return putInMap(new Node(type, childNodes, Kind.TYPE)); } - private Collection buildTree(FieldDeclaration[] children) { + private Collection buildFields(FieldDeclaration[] children) { if ( children == null ) return Collections.emptyList(); List childNodes = new ArrayList(); - for ( FieldDeclaration child : children ) addIfNotNull(childNodes, buildTree(child)); + for ( FieldDeclaration child : children ) addIfNotNull(childNodes, buildField(child)); return childNodes; } @@ -329,152 +318,97 @@ public class EclipseAST { else return Collections.singleton(item); } - private Node buildTree(FieldDeclaration field) { - if ( field instanceof Initializer ) return buildTree((Initializer)field); - if ( identityDetector.containsKey(field) ) return null; + private Node buildField(FieldDeclaration field) { + if ( field instanceof Initializer ) return buildInitializer((Initializer)field); + if ( alreadyHandled(field) ) return null; List childNodes = new ArrayList(); - addIfNotNull(childNodes, buildWithStatement(field.initialization)); - childNodes.addAll(buildTree(field.annotations)); - return putInMap(new Node(field, childNodes)); + addIfNotNull(childNodes, buildStatement(field.initialization)); + childNodes.addAll(buildAnnotations(field.annotations)); + return putInMap(new Node(field, childNodes, Kind.FIELD)); } - private Node buildTree(Initializer initializer) { - if ( identityDetector.containsKey(initializer) ) return null; - return putInMap(new Node(initializer, singleton(buildWithStatement(initializer.block)))); + private Node buildInitializer(Initializer initializer) { + if ( alreadyHandled(initializer) ) return null; + return putInMap(new Node(initializer, singleton(buildStatement(initializer.block)), Kind.INITIALIZER)); } - private Collection buildTree(AbstractMethodDeclaration[] children) { + private Collection buildMethods(AbstractMethodDeclaration[] children) { if ( children == null ) return Collections.emptyList(); List childNodes = new ArrayList(); - for (AbstractMethodDeclaration method : children ) addIfNotNull(childNodes, buildTree(method)); + for (AbstractMethodDeclaration method : children ) addIfNotNull(childNodes, buildMethod(method)); return childNodes; } - private Node buildTree(AbstractMethodDeclaration method) { - if ( identityDetector.containsKey(method) ) return null; + private Node buildMethod(AbstractMethodDeclaration method) { + if ( alreadyHandled(method) ) return null; List childNodes = new ArrayList(); - childNodes.addAll(buildTree(method.arguments)); - childNodes.addAll(buildTree(method.statements)); - childNodes.addAll(buildTree(method.annotations)); - return putInMap(new Node(method, childNodes)); + childNodes.addAll(buildArguments(method.arguments)); + childNodes.addAll(buildStatements(method.statements)); + childNodes.addAll(buildAnnotations(method.annotations)); + return putInMap(new Node(method, childNodes, Kind.METHOD)); } //Arguments are a kind of LocalDeclaration. They can definitely contain lombok annotations, so we care about them. - private Collection buildTree(Argument[] children) { + private Collection buildArguments(Argument[] children) { if ( children == null ) return Collections.emptyList(); List childNodes = new ArrayList(); for ( LocalDeclaration local : children ) { - addIfNotNull(childNodes, buildTree(local)); + addIfNotNull(childNodes, buildLocal(local)); } return childNodes; } - private Node buildTree(LocalDeclaration local) { - if ( identityDetector.containsKey(local) ) return null; + private Node buildLocal(LocalDeclaration local) { + if ( alreadyHandled(local) ) return null; List childNodes = new ArrayList(); - addIfNotNull(childNodes, buildWithStatement(local.initialization)); - childNodes.addAll(buildTree(local.annotations)); - return putInMap(new Node(local, childNodes)); + addIfNotNull(childNodes, buildStatement(local.initialization)); + childNodes.addAll(buildAnnotations(local.annotations)); + return putInMap(new Node(local, childNodes, Kind.LOCAL)); } - private Collection buildTree(Annotation[] annotations) { + private Collection buildAnnotations(Annotation[] annotations) { if ( annotations == null ) return Collections.emptyList(); List elements = new ArrayList(); for ( Annotation an : annotations ) { if ( an == null ) continue; - elements.add(putInMap(new Node(an, null))); + if ( alreadyHandled(an) ) continue; + elements.add(putInMap(new Node(an, null, Kind.ANNOTATION))); } return elements; } - private Collection buildTree(Statement[] children) { + private Collection buildStatements(Statement[] children) { if ( children == null ) return Collections.emptyList(); List childNodes = new ArrayList(); - for ( Statement child : children ) addIfNotNull(childNodes, buildWithStatement(child)); + for ( Statement child : children ) addIfNotNull(childNodes, buildStatement(child)); return childNodes; } //Almost anything is a statement, so this method has a different name to avoid overloading confusion - private Node buildWithStatement(Statement child) { - if ( child == null || identityDetector.containsKey(child) ) return null; - if ( child instanceof TypeDeclaration ) return buildTree((TypeDeclaration)child); + private Node buildStatement(Statement child) { + if ( child == null || alreadyHandled(child) ) return null; + if ( child instanceof TypeDeclaration ) return buildType((TypeDeclaration)child); - if ( child instanceof LocalDeclaration ) return buildTree((LocalDeclaration)child); + if ( child instanceof LocalDeclaration ) return buildLocal((LocalDeclaration)child); //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); + setAsHandled(child); return drill(child); } - private Node drill(Statement statement) { + protected Node drill(Statement statement) { List childNodes = new ArrayList(); - for ( FieldAccess fa : fieldsOf(statement.getClass()) ) childNodes.addAll(buildWithField(statement, fa)); - return putInMap(new Node(statement, childNodes)); - } - - private static class FieldAccess { - final Field field; - final int dim; - - FieldAccess(Field field, int dim) { - this.field = field; - this.dim = dim; - } - } - - private static Map, Collection> fieldsOfASTClasses = new HashMap, Collection>(); - private Collection fieldsOf(Class c) { - Collection fields = fieldsOfASTClasses.get(c); - if ( fields != null ) return fields; - - fields = new ArrayList(); - getFields(c, fields); - fieldsOfASTClasses.put(c, fields); - return fields; - } - - private void getFields(Class c, Collection fields) { - if ( c == ASTNode.class || c == null ) return; - for ( Field f : c.getDeclaredFields() ) { - if ( Modifier.isStatic(f.getModifiers()) ) continue; - Class t = f.getType(); - int dim = 0; - while ( t.isArray() ) { - dim++; - t = t.getComponentType(); - } - if ( Statement.class.isAssignableFrom(t) ) { - f.setAccessible(true); - fields.add(new FieldAccess(f, dim)); - } - } - getFields(c.getSuperclass(), fields); + for ( FieldAccess fa : fieldsOf(statement.getClass()) ) childNodes.addAll(buildWithField(Node.class, statement, fa)); + return putInMap(new Node(statement, childNodes, Kind.STATEMENT)); } - private Collection buildWithField(Statement statement, FieldAccess fa) { - List list = new ArrayList(); - buildWithField(statement, fa, list); - return list; + @Override protected Collection> getStatementTypes() { + return Collections.>singleton(Statement.class); } - private void buildWithField(Statement child, FieldAccess fa, Collection list) { - try { - Object o = fa.field.get(child); - if ( fa.dim == 0 ) addIfNotNull(list, buildWithStatement((Statement)o)); - else buildWithArray(o, list, fa.dim); - } catch ( IllegalAccessException e ) { - sneakyThrow(e); - } - } - - private void buildWithArray(Object array, Collection list, int dim) { - if ( array == null ) return; - if ( dim == 1 ) for ( Object v : (Object[])array ) { - addIfNotNull(list, buildWithStatement((Statement)v)); - } else for ( Object v : (Object[])array ) { - buildWithArray(v, list, dim-1); - } + @Override protected Node buildStatement(Object node) { + return buildStatement((Statement)node); } } diff --git a/src/lombok/eclipse/EclipseASTAdapter.java b/src/lombok/eclipse/EclipseASTAdapter.java index 1bd5ae3d..61d161d1 100644 --- a/src/lombok/eclipse/EclipseASTAdapter.java +++ b/src/lombok/eclipse/EclipseASTAdapter.java @@ -4,6 +4,7 @@ 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.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.Initializer; @@ -25,6 +26,9 @@ public abstract class EclipseASTAdapter implements EclipseASTVisitor { @Override public void visitMethod(Node methodNode, AbstractMethodDeclaration method) {} @Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) {} @Override public void endVisitMethod(Node methodNode, AbstractMethodDeclaration method) {} + @Override public void visitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method) {} + @Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) {} + @Override public void endVisitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method) {} @Override public void visitLocal(Node localNode, LocalDeclaration local) {} @Override public void visitAnnotationOnLocal(LocalDeclaration local, Node annotationNode, Annotation annotation) {} @Override public void endVisitLocal(Node localNode, LocalDeclaration local) {} diff --git a/src/lombok/eclipse/EclipseASTVisitor.java b/src/lombok/eclipse/EclipseASTVisitor.java index 9ab56ebe..0c55d222 100644 --- a/src/lombok/eclipse/EclipseASTVisitor.java +++ b/src/lombok/eclipse/EclipseASTVisitor.java @@ -60,8 +60,14 @@ public interface EclipseASTVisitor { 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). + * Visits a method argument + */ + void visitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method); + void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node annotationNode, Annotation annotation); + void endVisitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method); + + /** + * Visits a local declaration - that is, something like 'int x = 10;' on the method level. */ void visitLocal(Node localNode, LocalDeclaration local); void visitAnnotationOnLocal(LocalDeclaration local, Node annotationNode, Annotation annotation); @@ -69,8 +75,6 @@ public interface EclipseASTVisitor { /** * Visits a statement that isn't any of the other visit methods (e.g. TypeDeclaration). - * @param node - * @param statement */ void visitStatement(Node statementNode, Statement statement); void endVisitStatement(Node statementNode, Statement statement); @@ -171,9 +175,22 @@ public interface EclipseASTVisitor { print("", type, str(method.selector)); } + @Override public void visitMethodArgument(Node node, Argument arg, AbstractMethodDeclaration method) { + print("", str(arg.type), str(arg.name), arg.initialization); + indent++; + } + + @Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node node, Annotation annotation) { + print("", annotation); + } + + @Override public void endVisitMethodArgument(Node node, Argument arg, AbstractMethodDeclaration method) { + indent--; + print("", str(arg.type), str(arg.name)); + } + @Override public void visitLocal(Node node, LocalDeclaration local) { - String type = local instanceof Argument ? "ARGUMENT" : "LOCAL"; - print("<%s %s %s = %s>", type, str(local.type), str(local.name), local.initialization); + print("", str(local.type), str(local.name), local.initialization); indent++; } @@ -182,9 +199,8 @@ public interface EclipseASTVisitor { } @Override public void endVisitLocal(Node node, LocalDeclaration local) { - String type = local instanceof Argument ? "ARGUMENT" : "LOCAL"; indent--; - print("", type, str(local.type), str(local.name)); + print("", str(local.type), str(local.name)); } @Override public void visitStatement(Node node, Statement statement) { diff --git a/src/lombok/eclipse/EclipseAnnotationHandler.java b/src/lombok/eclipse/EclipseAnnotationHandler.java index c6cc23be..816ba61c 100644 --- a/src/lombok/eclipse/EclipseAnnotationHandler.java +++ b/src/lombok/eclipse/EclipseAnnotationHandler.java @@ -1,5 +1,7 @@ package lombok.eclipse; +import lombok.core.AnnotationValues; + public interface EclipseAnnotationHandler { - void handle(T annotation, org.eclipse.jdt.internal.compiler.ast.Annotation ast, EclipseAST.Node annotationNode); + void handle(AnnotationValues annotation, org.eclipse.jdt.internal.compiler.ast.Annotation ast, EclipseAST.Node annotationNode); } diff --git a/src/lombok/eclipse/HandlerLibrary.java b/src/lombok/eclipse/HandlerLibrary.java index 8a7f6edc..2e3e4541 100644 --- a/src/lombok/eclipse/HandlerLibrary.java +++ b/src/lombok/eclipse/HandlerLibrary.java @@ -1,34 +1,36 @@ package lombok.eclipse; +import static lombok.eclipse.Eclipse.toQualifiedName; + import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; -import java.lang.reflect.Proxy; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; +import lombok.core.AnnotationValues; import lombok.core.SpiLoadUtil; import lombok.core.TypeLibrary; +import lombok.core.TypeResolver; +import lombok.core.AnnotationValues.AnnotationValue; +import lombok.core.AnnotationValues.AnnotationValueDecodeFail; import lombok.eclipse.EclipseAST.Node; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.Expression; -import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Literal; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; -import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public class HandlerLibrary { @@ -43,11 +45,56 @@ public class HandlerLibrary { this.annotationClass = annotationClass; } - @SuppressWarnings("unchecked") - public void handle(Object annInstance, - org.eclipse.jdt.internal.compiler.ast.Annotation annotation, - Node annotationNode) { - handler.handle((T) annInstance, annotation, annotationNode); + public void handle(org.eclipse.jdt.internal.compiler.ast.Annotation annotation, + final Node annotationNode) { + Map values = new HashMap(); + + final MemberValuePair[] pairs = annotation.memberValuePairs(); + for ( Method m : annotationClass.getDeclaredMethods() ) { + if ( !Modifier.isPublic(m.getModifiers()) ) continue; + String name = m.getName(); + List raws = new ArrayList(); + List guesses = new ArrayList(); + Expression fullExpression = null; + Expression[] expressions = null; + + if ( pairs != null ) for ( MemberValuePair pair : pairs ) { + char[] n = pair.name; + String mName = n == null ? "value" : new String(name); + if ( !mName.equals(name) ) continue; + fullExpression = pair.value; + } + + if ( fullExpression != null ) { + if ( fullExpression instanceof ArrayInitializer ) { + expressions = ((ArrayInitializer)fullExpression).expressions; + } else expressions = new Expression[] { fullExpression }; + for ( Expression ex : expressions ) { + StringBuffer sb = new StringBuffer(); + ex.print(0, sb); + raws.add(sb.toString()); + guesses.add(calculateValue(ex)); + } + } + + final Expression fullExpr = fullExpression; + final Expression[] exprs = expressions; + + values.put(name, new AnnotationValue(annotationNode, raws, guesses) { + @Override public void setError(String message, int valueIdx) { + Expression ex; + if ( valueIdx == -1 ) ex = fullExpr; + else ex = exprs[valueIdx]; + + int sourceStart = ex.sourceStart; + int sourceEnd = ex.sourceEnd; + + annotationNode.addError(message, sourceStart, sourceEnd); + } + }); + } + + handler.handle(new AnnotationValues(annotationClass, values, annotationNode), annotation, annotationNode); } } @@ -56,192 +103,32 @@ public class HandlerLibrary { private Collection visitorHandlers = new ArrayList(); - @SuppressWarnings("unchecked") - public A createAnnotation(Class target, - CompilationUnitDeclaration ast, - org.eclipse.jdt.internal.compiler.ast.Annotation node) throws AnnotationValueDecodeFail { - final Map values = new HashMap(); - - final MemberValuePair[] pairs = node.memberValuePairs(); - - for ( Method m : target.getMethods() ) { - String name = m.getName(); - Object value = m.getDefaultValue(); - for ( MemberValuePair pair : pairs ) { - if ( name.equals(new String(pair.name)) ) { - value = calculateValue(pair, ast, m.getReturnType(), pair.value); - break; - } - } - values.put(name, value); - } - - InvocationHandler invocations = new InvocationHandler() { - @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - return values.get(method.getName()); - } - }; - - return (A) Proxy.newProxyInstance(target.getClassLoader(), new Class[] { target }, invocations); - } - - private Object calculateValue(MemberValuePair pair, - CompilationUnitDeclaration ast, Class type, Expression e) throws AnnotationValueDecodeFail { + private static Object calculateValue(Expression e) { if ( e instanceof Literal ) { ((Literal)e).computeConstant(); - return convertConstant(pair, type, e.constant); - } else if ( e instanceof ArrayInitializer ) { - if ( !type.isArray() ) throw new AnnotationValueDecodeFail(pair, "Did not expect an array here."); - - Class component = type.getComponentType(); - Expression[] expressions = ((ArrayInitializer)e).expressions; - int length = expressions == null ? 0 : expressions.length; - Object[] values = new Object[length]; - for (int i = 0; i < length; i++) { - values[i] = calculateValue(pair, ast, component, expressions[i]); + switch ( e.constant.typeID() ) { + case TypeIds.T_int: return e.constant.intValue(); + case TypeIds.T_byte: return e.constant.byteValue(); + case TypeIds.T_short: return e.constant.shortValue(); + case TypeIds.T_char: return e.constant.charValue(); + case TypeIds.T_float: return e.constant.floatValue(); + case TypeIds.T_double: return e.constant.doubleValue(); + case TypeIds.T_boolean: return e.constant.booleanValue(); + case TypeIds.T_long: return e.constant.longValue(); + case TypeIds.T_JavaLangString: return e.constant.stringValue(); + default: return null; } - return values; } else if ( e instanceof ClassLiteralAccess ) { - if ( type == Class.class ) return toClass(pair, ast, str(((ClassLiteralAccess)e).type.getTypeName())); - else throw new AnnotationValueDecodeFail(pair, "Expected a " + type + " literal."); - } else if ( e instanceof NameReference ) { - String s = null; - if ( e instanceof SingleNameReference ) s = new String(((SingleNameReference)e).token); - else if ( e instanceof QualifiedNameReference ) s = str(((QualifiedNameReference)e).tokens); - if ( Enum.class.isAssignableFrom(type) ) return toEnum(pair, type, s); - throw new AnnotationValueDecodeFail(pair, "Lombok annotations must contain literals only."); - } else { - throw new AnnotationValueDecodeFail(pair, "Lombok could not decode this annotation parameter."); - } - } - - private Enum toEnum(MemberValuePair pair, Class enumType, String ref) throws AnnotationValueDecodeFail { - int idx = ref.indexOf('.'); - if ( idx > -1 ) ref = ref.substring(idx +1); - Object[] enumConstants = enumType.getEnumConstants(); - for ( Object constant : enumConstants ) { - String target = ((Enum)constant).name(); - if ( target.equals(ref) ) return (Enum) constant; + return Eclipse.toQualifiedName(((ClassLiteralAccess)e).type.getTypeName()); + } else if ( e instanceof SingleNameReference ) { + return new String(((SingleNameReference)e).token); + } else if ( e instanceof QualifiedNameReference ) { + String qName = Eclipse.toQualifiedName(((QualifiedNameReference)e).tokens); + int idx = qName.lastIndexOf('.'); + return idx == -1 ? qName : qName.substring(idx+1); } - throw new AnnotationValueDecodeFail(pair, "I can't figure out which enum constant you mean."); - } - - private Class toClass(MemberValuePair pair, CompilationUnitDeclaration ast, String typeName) throws AnnotationValueDecodeFail { - Class c; - boolean fqn = typeName.indexOf('.') > -1; - - if ( fqn ) { - c = tryClass(typeName); - if ( c != null ) return c; - } - - for ( ImportReference ref : ast.imports ) { - String im = str(ref.tokens); - int idx = im.lastIndexOf('.'); - String simple = im; - if ( idx > -1 ) simple = im.substring(idx+1); - if ( simple.equals(typeName) ) { - c = tryClass(im); - if ( c != null ) return c; - } - } - - if ( ast.currentPackage != null && ast.currentPackage.tokens != null ) { - String pkg = str(ast.currentPackage.tokens); - c = tryClass(pkg + "." + typeName); - if ( c != null ) return c; - } - - c = tryClass("java.lang." + typeName); - if ( c != null ) return c; - if ( !fqn ) { - c = tryClass(typeName); - if ( c != null ) return c; - } - - //Try star imports - for ( ImportReference ref : ast.imports ) { - String im = str(ref.tokens); - if ( im.endsWith(".*") ) { - c = tryClass(im.substring(0, im.length() -1) + typeName); - if ( c != null ) return c; - } - } - - throw new AnnotationValueDecodeFail(pair, "I can't find this class. Try using the fully qualified name."); - } - - private Class tryClass(String name) { - try { - return Class.forName(name); - } catch ( ClassNotFoundException e ) { - return null; - } - } - - private Object convertConstant(MemberValuePair pair, Class type, Constant constant) throws AnnotationValueDecodeFail { - int targetTypeID; - boolean array = type.isArray(); - if ( array ) type = type.getComponentType(); - - if ( type == int.class ) targetTypeID = TypeIds.T_int; - else if ( type == long.class ) targetTypeID = TypeIds.T_long; - else if ( type == short.class ) targetTypeID = TypeIds.T_short; - else if ( type == byte.class ) targetTypeID = TypeIds.T_byte; - else if ( type == double.class ) targetTypeID = TypeIds.T_double; - else if ( type == float.class ) targetTypeID = TypeIds.T_float; - else if ( type == String.class ) targetTypeID = TypeIds.T_JavaLangString; - else if ( type == char.class ) targetTypeID = TypeIds.T_char; - else if ( type == boolean.class ) targetTypeID = TypeIds.T_boolean; - else { - //Enum or Class, so a constant isn't going to be very useful. - throw new AnnotationValueDecodeFail(pair, "Expected a constant of some sort here (a number or a string)"); - } - if ( !Expression.isConstantValueRepresentable(constant, constant.typeID(), targetTypeID) ) { - throw new AnnotationValueDecodeFail(pair, "I can't turn this literal into a " + type); - } - - Object o = null; - - if ( type == int.class ) o = constant.intValue(); - else if ( type == long.class ) o = constant.longValue(); - else if ( type == short.class ) o = constant.shortValue(); - else if ( type == byte.class ) o = constant.byteValue(); - else if ( type == double.class ) o = constant.doubleValue(); - else if ( type == float.class ) o = constant.floatValue(); - else if ( type == String.class ) o = constant.stringValue(); - else if ( type == char.class ) o = constant.charValue(); - else if ( type == boolean.class ) o = constant.booleanValue(); - - if ( array ) { - Object a = Array.newInstance(type, 1); - Array.set(a, 0, o); - return a; - } - - return o; - } - - private static class AnnotationValueDecodeFail extends Exception { - private static final long serialVersionUID = 1L; - - MemberValuePair pair; - - AnnotationValueDecodeFail(MemberValuePair pair, String msg) { - super(msg); - this.pair = pair; - } - } - - private static String str(char[][] c) { - boolean first = true; - StringBuilder sb = new StringBuilder(); - for ( char[] part : c ) { - sb.append(first ? "" : ".").append(part); - first = false; - } - return sb.toString(); + return null; } public static HandlerLibrary load() { @@ -284,22 +171,20 @@ public class HandlerLibrary { public void handle(CompilationUnitDeclaration ast, EclipseAST.Node annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation) { - TypeResolver resolver = new TypeResolver(typeLibrary, annotationNode.top()); + String pkgName = annotationNode.getPackageDeclaration(); + Collection imports = annotationNode.getImportStatements(); + + TypeResolver resolver = new TypeResolver(typeLibrary, pkgName, imports); TypeReference rawType = annotation.type; if ( rawType == null ) return; - for ( String fqn : resolver.findTypeMatches(annotationNode, annotation.type) ) { + for ( String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName())) ) { AnnotationHandlerContainer container = annotationHandlers.get(fqn); if ( container == null ) continue; - Object annInstance; - try { - annInstance = createAnnotation(container.annotationClass, ast, annotation); - } catch ( AnnotationValueDecodeFail e ) { - annotationNode.addError(e.getMessage(), e.pair.sourceStart, e.pair.sourceEnd); - return; - } try { - container.handle(annInstance, annotation, annotationNode); + container.handle(annotation, annotationNode); + } catch ( AnnotationValueDecodeFail fail ) { + fail.owner.setError(fail.getMessage(), fail.idx); } catch ( Throwable t ) { Eclipse.error(String.format("Lombok annotation handler %s failed", container.handler.getClass()), t); } diff --git a/src/lombok/eclipse/TransformEclipseAST.java b/src/lombok/eclipse/TransformEclipseAST.java index 55cdd822..f77639e1 100644 --- a/src/lombok/eclipse/TransformEclipseAST.java +++ b/src/lombok/eclipse/TransformEclipseAST.java @@ -6,6 +6,7 @@ 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.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; @@ -114,25 +115,31 @@ public class TransformEclipseAST { private static class AnnotationVisitor extends EclipseASTAdapter { @Override public void visitAnnotationOnField(FieldDeclaration field, Node annotationNode, Annotation annotation) { if ( annotationNode.isHandled() ) return; - handlers.handle((CompilationUnitDeclaration) annotationNode.top().node, annotationNode, annotation); + handlers.handle((CompilationUnitDeclaration) annotationNode.top().get(), annotationNode, annotation); + annotationNode.setHandled(); + } + + @Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) { + if ( annotationNode.isHandled() ) return; + handlers.handle((CompilationUnitDeclaration) annotationNode.top().get(), annotationNode, annotation); annotationNode.setHandled(); } @Override public void visitAnnotationOnLocal(LocalDeclaration local, Node annotationNode, Annotation annotation) { if ( annotationNode.isHandled() ) return; - handlers.handle((CompilationUnitDeclaration) annotationNode.top().node, annotationNode, annotation); + handlers.handle((CompilationUnitDeclaration) annotationNode.top().get(), annotationNode, annotation); annotationNode.setHandled(); } @Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) { if ( annotationNode.isHandled() ) return; - handlers.handle((CompilationUnitDeclaration) annotationNode.top().node, annotationNode, annotation); + handlers.handle((CompilationUnitDeclaration) annotationNode.top().get(), annotationNode, annotation); annotationNode.setHandled(); } @Override public void visitAnnotationOnType(TypeDeclaration type, Node annotationNode, Annotation annotation) { if ( annotationNode.isHandled() ) return; - handlers.handle((CompilationUnitDeclaration) annotationNode.top().node, annotationNode, annotation); + handlers.handle((CompilationUnitDeclaration) annotationNode.top().get(), annotationNode, annotation); annotationNode.setHandled(); } } diff --git a/src/lombok/eclipse/TypeResolver.java b/src/lombok/eclipse/TypeResolver.java deleted file mode 100644 index 41618513..00000000 --- a/src/lombok/eclipse/TypeResolver.java +++ /dev/null @@ -1,100 +0,0 @@ -package lombok.eclipse; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import lombok.core.TypeLibrary; -import lombok.eclipse.EclipseAST.Node; - -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; -import org.eclipse.jdt.internal.compiler.ast.ImportReference; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; -import org.eclipse.jdt.internal.compiler.ast.TypeReference; - -public class TypeResolver { - private final TypeLibrary library; - private Collection imports; - - - public TypeResolver(TypeLibrary library, EclipseAST.Node top) { - this.library = library; - this.imports = makeImportList((CompilationUnitDeclaration) top.getEclipseNode()); - } - - private static Collection makeImportList(CompilationUnitDeclaration declaration) { - Set imports = new HashSet(); - if ( declaration.currentPackage != null ) imports.add(toQualifiedName(declaration.currentPackage.getImportName()) + ".*"); - if ( declaration.imports != null ) for ( ImportReference importStatement : declaration.imports ) { - imports.add(toQualifiedName(importStatement.getImportName())); - } - return imports; - } - - public Collection findTypeMatches(Node context, TypeReference type) { - Collection potentialMatches = library.findCompatible(toQualifiedName(type.getTypeName())); - if ( potentialMatches.isEmpty() ) return Collections.emptyList(); - - if ( type.getTypeName().length > 1 ) return potentialMatches; - - String simpleName = new String(type.getTypeName()[0]); - - //If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches. - if ( nameConflictInImportList(simpleName, potentialMatches) ) return Collections.emptyList(); - - //Check if any of our potentials is even imported in the first place. If not: no matches. - potentialMatches = eliminateImpossibleMatches(potentialMatches); - if ( potentialMatches.isEmpty() ) return Collections.emptyList(); - - //Find a lexically accessible type of the same simple name in the same Compilation Unit. If it exists: no matches. - Node n = context; - while ( n != null ) { - if ( n.getEclipseNode() instanceof TypeDeclaration ) { - char[] name = ((TypeDeclaration)n.getEclipseNode()).name; - if ( name != null && new String(name).equals(simpleName) ) return Collections.emptyList(); - } - n = n.up(); - } - - // The potential matches we found by comparing the import statements is our matching set. Return it. - return potentialMatches; - } - - private Collection eliminateImpossibleMatches(Collection potentialMatches) { - Set results = new HashSet(); - - for ( String importedType : imports ) { - Collection reduced = library.findCompatible(importedType); - reduced.retainAll(potentialMatches); - results.addAll(reduced); - } - - return results; - } - - private boolean nameConflictInImportList(String simpleName, Collection potentialMatches) { - for ( String importedType : imports ) { - if ( !toSimpleName(importedType).equals(simpleName) ) continue; - if ( potentialMatches.contains(importedType) ) continue; - return true; - } - - return false; - } - - private static String toSimpleName(String typeName) { - int idx = typeName.lastIndexOf('.'); - return idx == -1 ? typeName : typeName.substring(idx+1); - } - - private static String toQualifiedName(char[][] typeName) { - StringBuilder sb = new StringBuilder(); - boolean first = true; - for ( char[] c : typeName ) { - sb.append(first ? "" : ".").append(c); - first = false; - } - return sb.toString(); - } -} diff --git a/src/lombok/eclipse/handlers/HandleGetter_ecj.java b/src/lombok/eclipse/handlers/HandleGetter_ecj.java index f9bbb884..cde71f83 100644 --- a/src/lombok/eclipse/handlers/HandleGetter_ecj.java +++ b/src/lombok/eclipse/handlers/HandleGetter_ecj.java @@ -4,6 +4,7 @@ import java.lang.reflect.Modifier; import lombok.AccessLevel; import lombok.Getter; +import lombok.core.AnnotationValues; import lombok.core.TransformationsUtil; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseAST.Node; @@ -28,14 +29,14 @@ public class HandleGetter_ecj implements EclipseAnnotationHandler { annotationNode.addWarning(String.format("Not generating %s(): A method with that name already exists", methodName)); } - @Override public void handle(Getter annotation, Annotation ast, Node annotationNode) { - if ( !(annotationNode.up().getEclipseNode() instanceof FieldDeclaration) ) return; - FieldDeclaration field = (FieldDeclaration) annotationNode.up().getEclipseNode(); + @Override public void handle(AnnotationValues annotation, Annotation ast, Node annotationNode) { + if ( !(annotationNode.up().get() instanceof FieldDeclaration) ) return; + FieldDeclaration field = (FieldDeclaration) annotationNode.up().get(); TypeReference fieldType = field.type; String getterName = TransformationsUtil.toGetterName( new String(field.name), nameEquals(fieldType.getTypeName(), "boolean")); - TypeDeclaration parent = (TypeDeclaration) annotationNode.up().up().getEclipseNode(); + TypeDeclaration parent = (TypeDeclaration) annotationNode.up().up().get(); if ( parent.methods != null ) for ( AbstractMethodDeclaration method : parent.methods ) { if ( method.selector != null && new String(method.selector).equals(getterName) ) { generateDuplicateGetterWarning(annotationNode, getterName); @@ -44,7 +45,7 @@ public class HandleGetter_ecj implements EclipseAnnotationHandler { } MethodDeclaration method = new MethodDeclaration(parent.compilationResult); - method.modifiers = toModifier(annotation.value()); + method.modifiers = toModifier(annotation.getInstance().value()); method.returnType = field.type; method.annotations = null; method.arguments = null; -- cgit