diff options
-rw-r--r-- | src/lombok/core/AST.java | 13 | ||||
-rw-r--r-- | src/lombok/eclipse/EclipseAST.java | 53 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleData.java | 12 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleSetter.java | 3 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/PKG.java | 58 | ||||
-rw-r--r-- | src/lombok/javac/JavacAST.java | 18 |
6 files changed, 89 insertions, 68 deletions
diff --git a/src/lombok/core/AST.java b/src/lombok/core/AST.java index febe53ab..2f92ad6d 100644 --- a/src/lombok/core/AST.java +++ b/src/lombok/core/AST.java @@ -9,7 +9,6 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; @@ -52,12 +51,10 @@ public abstract class AST<N> { nodeMap = new IdentityHashMap<N, Node>(); } - protected boolean alreadyHandled(N node) { - return identityDetector.containsKey(node); - } - - protected void setAsHandled(N node) { + protected boolean setAndGetAsHandled(N node) { + if ( identityDetector.containsKey(node) ) return true; identityDetector.put(node, null); + return false; } public String getFileName() { @@ -100,7 +97,7 @@ public abstract class AST<N> { protected Node(N node, List<? extends Node> children, Kind kind) { this.kind = kind; this.node = node; - this.children = children == null ? Collections.<Node>emptyList() : children; + this.children = children == null ? new ArrayList<Node>() : children; for ( Node child : this.children ) child.parent = this; this.isStructurallySignificant = calculateIsStructurallySignificant(); } @@ -218,8 +215,8 @@ public abstract class AST<N> { private void gatherAndRemoveChildren(Map<N, Node> map) { for ( Node child : children ) child.gatherAndRemoveChildren(map); - map.put(get(), this); identityDetector.remove(get()); + map.put(get(), this); children.clear(); nodeMap.remove(get()); } diff --git a/src/lombok/eclipse/EclipseAST.java b/src/lombok/eclipse/EclipseAST.java index 5b2b153d..5018f484 100644 --- a/src/lombok/eclipse/EclipseAST.java +++ b/src/lombok/eclipse/EclipseAST.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import lombok.core.AST; @@ -49,7 +48,7 @@ public class EclipseAST extends AST<ASTNode> { top().traverse(visitor); } - private void traverseChildren(EclipseASTVisitor visitor, Node node) { + void traverseChildren(EclipseASTVisitor visitor, Node node) { for ( Node child : node.down() ) { child.traverse(visitor); } @@ -306,15 +305,8 @@ public class EclipseAST extends AST<ASTNode> { if ( completeParse ) return; boolean newCompleteParse = isComplete(compilationUnitDeclaration); if ( !newCompleteParse ) return; - Map<ASTNode, AST<ASTNode>.Node> oldMap = getNodeMap(); - clearState(); - setTop(buildCompilationUnit(compilationUnitDeclaration)); - //Retain 'handled' flags. - for ( Map.Entry<ASTNode, AST<ASTNode>.Node> e : getNodeMap().entrySet() ) { - Node oldEntry = (Node) oldMap.get(e.getKey()); - if ( oldEntry != null && oldEntry.isHandled() ) e.getValue().setHandled(); - } + top().rebuild(); this.completeParse = true; } @@ -349,6 +341,7 @@ public class EclipseAST extends AST<ASTNode> { } private Node buildCompilationUnit(CompilationUnitDeclaration top) { + if ( setAndGetAsHandled(top) ) return null; List<Node> children = buildTypes(top.types); return putInMap(new Node(top, children, Kind.COMPILATION_UNIT)); } @@ -358,14 +351,13 @@ public class EclipseAST extends AST<ASTNode> { } private List<Node> buildTypes(TypeDeclaration[] children) { - if ( children == null ) return Collections.emptyList(); List<Node> childNodes = new ArrayList<Node>(); - for ( TypeDeclaration type : children ) addIfNotNull(childNodes, buildType(type)); + if ( children != null ) for ( TypeDeclaration type : children ) addIfNotNull(childNodes, buildType(type)); return childNodes; } private Node buildType(TypeDeclaration type) { - if ( alreadyHandled(type) ) return null; + if ( setAndGetAsHandled(type) ) return null; List<Node> childNodes = new ArrayList<Node>(); childNodes.addAll(buildFields(type.fields)); childNodes.addAll(buildTypes(type.memberTypes)); @@ -375,20 +367,20 @@ public class EclipseAST extends AST<ASTNode> { } private Collection<Node> buildFields(FieldDeclaration[] children) { - if ( children == null ) return Collections.emptyList(); List<Node> childNodes = new ArrayList<Node>(); - for ( FieldDeclaration child : children ) addIfNotNull(childNodes, buildField(child)); + if ( children != null ) for ( FieldDeclaration child : children ) addIfNotNull(childNodes, buildField(child)); return childNodes; } private static <T> List<T> singleton(T item) { - if ( item == null ) return Collections.emptyList(); - else return Collections.singletonList(item); + List<T> list = new ArrayList<T>(); + if ( item != null ) list.add(item); + return list; } private Node buildField(FieldDeclaration field) { if ( field instanceof Initializer ) return buildInitializer((Initializer)field); - if ( alreadyHandled(field) ) return null; + if ( setAndGetAsHandled(field) ) return null; List<Node> childNodes = new ArrayList<Node>(); addIfNotNull(childNodes, buildStatement(field.initialization)); childNodes.addAll(buildAnnotations(field.annotations)); @@ -396,19 +388,18 @@ public class EclipseAST extends AST<ASTNode> { } private Node buildInitializer(Initializer initializer) { - if ( alreadyHandled(initializer) ) return null; + if ( setAndGetAsHandled(initializer) ) return null; return putInMap(new Node(initializer, singleton(buildStatement(initializer.block)), Kind.INITIALIZER)); } private Collection<Node> buildMethods(AbstractMethodDeclaration[] children) { - if ( children == null ) return Collections.emptyList(); List<Node> childNodes = new ArrayList<Node>(); - for (AbstractMethodDeclaration method : children ) addIfNotNull(childNodes, buildMethod(method)); + if ( children != null ) for (AbstractMethodDeclaration method : children ) addIfNotNull(childNodes, buildMethod(method)); return childNodes; } private Node buildMethod(AbstractMethodDeclaration method) { - if ( alreadyHandled(method) ) return null; + if ( setAndGetAsHandled(method) ) return null; List<Node> childNodes = new ArrayList<Node>(); childNodes.addAll(buildArguments(method.arguments)); childNodes.addAll(buildStatements(method.statements)); @@ -418,16 +409,15 @@ public class EclipseAST extends AST<ASTNode> { //Arguments are a kind of LocalDeclaration. They can definitely contain lombok annotations, so we care about them. private Collection<Node> buildArguments(Argument[] children) { - if ( children == null ) return Collections.emptyList(); List<Node> childNodes = new ArrayList<Node>(); - for ( LocalDeclaration local : children ) { + if ( children != null ) for ( LocalDeclaration local : children ) { addIfNotNull(childNodes, buildLocal(local, Kind.ARGUMENT)); } return childNodes; } private Node buildLocal(LocalDeclaration local, Kind kind) { - if ( alreadyHandled(local) ) return null; + if ( setAndGetAsHandled(local) ) return null; List<Node> childNodes = new ArrayList<Node>(); addIfNotNull(childNodes, buildStatement(local.initialization)); childNodes.addAll(buildAnnotations(local.annotations)); @@ -435,32 +425,31 @@ public class EclipseAST extends AST<ASTNode> { } private Collection<Node> buildAnnotations(Annotation[] annotations) { - if ( annotations == null ) return Collections.emptyList(); List<Node> elements = new ArrayList<Node>(); - for ( Annotation an : annotations ) addIfNotNull(elements, buildAnnotation(an)); + if ( annotations != null ) for ( Annotation an : annotations ) addIfNotNull(elements, buildAnnotation(an)); return elements; } private Node buildAnnotation(Annotation annotation) { if ( annotation == null ) return null; - if ( alreadyHandled(annotation) ) return null; + if ( setAndGetAsHandled(annotation) ) return null; return putInMap(new Node(annotation, null, Kind.ANNOTATION)); } private Collection<Node> buildStatements(Statement[] children) { - if ( children == null ) return Collections.emptyList(); List<Node> childNodes = new ArrayList<Node>(); - for ( Statement child : children ) addIfNotNull(childNodes, buildStatement(child)); + if ( children != null ) for ( Statement child : children ) addIfNotNull(childNodes, buildStatement(child)); return childNodes; } private Node buildStatement(Statement child) { - if ( child == null || alreadyHandled(child) ) return null; + if ( child == null ) return null; if ( child instanceof TypeDeclaration ) return buildType((TypeDeclaration)child); if ( child instanceof LocalDeclaration ) return buildLocal((LocalDeclaration)child, Kind.LOCAL); - setAsHandled(child); + if ( setAndGetAsHandled(child) ) return null; + return drill(child); } diff --git a/src/lombok/eclipse/handlers/HandleData.java b/src/lombok/eclipse/handlers/HandleData.java index c17757c9..84db0df1 100644 --- a/src/lombok/eclipse/handlers/HandleData.java +++ b/src/lombok/eclipse/handlers/HandleData.java @@ -19,7 +19,7 @@ import lombok.core.AST.Kind; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseAST.Node; -import lombok.eclipse.handlers.PKG.MethodExistsResult; +import lombok.eclipse.handlers.PKG.MemberExistsResult; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; @@ -98,31 +98,31 @@ public class HandleData implements EclipseAnnotationHandler<Data> { new HandleSetter().generateSetterForField(child, annotationNode.get()); } - if ( methodExists("toString", typeNode) == MethodExistsResult.NOT_EXISTS ) { + if ( methodExists("toString", typeNode) == MemberExistsResult.NOT_EXISTS ) { MethodDeclaration toString = createToString(typeNode, nodesForConstructorAndToString, ast); injectMethod(typeNode, toString); } - if ( constructorExists(typeNode) == MethodExistsResult.NOT_EXISTS ) { + if ( constructorExists(typeNode) == MemberExistsResult.NOT_EXISTS ) { ConstructorDeclaration constructor = createConstructor( ann.staticConstructor().length() == 0, typeNode, nodesForConstructorAndToString, ast); injectMethod(typeNode, constructor); } if ( ann.staticConstructor().length() > 0 ) { - if ( methodExists("of", typeNode) == MethodExistsResult.NOT_EXISTS ) { + if ( methodExists("of", typeNode) == MemberExistsResult.NOT_EXISTS ) { MethodDeclaration staticConstructor = createStaticConstructor( ann.staticConstructor(), typeNode, nodesForConstructorAndToString, ast); injectMethod(typeNode, staticConstructor); } } - if ( methodExists("equals", typeNode) == MethodExistsResult.NOT_EXISTS ) { + if ( methodExists("equals", typeNode) == MemberExistsResult.NOT_EXISTS ) { MethodDeclaration equals = createEquals(typeNode, nodesForEquality, ast); injectMethod(typeNode, equals); } - if ( methodExists("hashCode", typeNode) == MethodExistsResult.NOT_EXISTS ) { + if ( methodExists("hashCode", typeNode) == MemberExistsResult.NOT_EXISTS ) { MethodDeclaration hashCode = createHashCode(typeNode, nodesForEquality, ast); injectMethod(typeNode, hashCode); } diff --git a/src/lombok/eclipse/handlers/HandleSetter.java b/src/lombok/eclipse/handlers/HandleSetter.java index 28332bdd..57dabc03 100644 --- a/src/lombok/eclipse/handlers/HandleSetter.java +++ b/src/lombok/eclipse/handlers/HandleSetter.java @@ -103,9 +103,8 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { method.typeParameters = null; method.scope = parent.scope == null ? null : new MethodScope(parent.scope, method, false); method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; - FieldReference thisX = new FieldReference(("this." + new String(field.name)).toCharArray(), pos); + FieldReference thisX = new FieldReference(field.name, pos); thisX.receiver = new ThisReference(ast.sourceStart, ast.sourceEnd); - thisX.token = field.name; Assignment assignment = new Assignment(thisX, new SingleNameReference(field.name, pos), (int)pos); method.bodyStart = method.declarationSourceStart = method.sourceStart = ast.sourceStart; method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = ast.sourceEnd; diff --git a/src/lombok/eclipse/handlers/PKG.java b/src/lombok/eclipse/handlers/PKG.java index e9d12b62..13492b28 100644 --- a/src/lombok/eclipse/handlers/PKG.java +++ b/src/lombok/eclipse/handlers/PKG.java @@ -9,6 +9,7 @@ import lombok.eclipse.EclipseAST; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; class PKG { @@ -41,11 +42,32 @@ class PKG { return string.contentEquals(sb); } - enum MethodExistsResult { + enum MemberExistsResult { NOT_EXISTS, EXISTS_BY_USER, EXISTS_BY_LOMBOK; } - static MethodExistsResult methodExists(String methodName, EclipseAST.Node node) { + static MemberExistsResult fieldExists(String fieldName, EclipseAST.Node node) { + while ( node != null && !(node.get() instanceof TypeDeclaration) ) { + node = node.up(); + } + + if ( node != null && node.get() instanceof TypeDeclaration ) { + TypeDeclaration typeDecl = (TypeDeclaration)node.get(); + if ( typeDecl.fields != null ) for ( FieldDeclaration def : typeDecl.fields ) { + char[] fName = def.name; + if ( fName == null ) continue; + if ( fieldName.equals(new String(fName)) ) { + EclipseAST.Node existing = node.getNodeFor(def); + if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER; + return MemberExistsResult.EXISTS_BY_LOMBOK; + } + } + } + + return MemberExistsResult.NOT_EXISTS; + } + + static MemberExistsResult methodExists(String methodName, EclipseAST.Node node) { while ( node != null && !(node.get() instanceof TypeDeclaration) ) { node = node.up(); } @@ -53,20 +75,20 @@ class PKG { if ( node != null && node.get() instanceof TypeDeclaration ) { TypeDeclaration typeDecl = (TypeDeclaration)node.get(); if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) { - char[] mName = ((AbstractMethodDeclaration)def).selector; + char[] mName = def.selector; if ( mName == null ) continue; if ( methodName.equals(new String(mName)) ) { EclipseAST.Node existing = node.getNodeFor(def); - if ( existing == null || !existing.isHandled() ) return MethodExistsResult.EXISTS_BY_USER; - return MethodExistsResult.EXISTS_BY_LOMBOK; + if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER; + return MemberExistsResult.EXISTS_BY_LOMBOK; } } } - return MethodExistsResult.NOT_EXISTS; + return MemberExistsResult.NOT_EXISTS; } - static MethodExistsResult constructorExists(EclipseAST.Node node) { + static MemberExistsResult constructorExists(EclipseAST.Node node) { while ( node != null && !(node.get() instanceof TypeDeclaration) ) { node = node.up(); } @@ -77,13 +99,13 @@ class PKG { if ( def instanceof ConstructorDeclaration ) { if ( (def.bits & ASTNode.IsDefaultConstructor) != 0 ) continue; EclipseAST.Node existing = node.getNodeFor(def); - if ( existing == null || !existing.isHandled() ) return MethodExistsResult.EXISTS_BY_USER; - return MethodExistsResult.EXISTS_BY_LOMBOK; + if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER; + return MemberExistsResult.EXISTS_BY_LOMBOK; } } } - return MethodExistsResult.NOT_EXISTS; + return MemberExistsResult.NOT_EXISTS; } static EclipseAST.Node getExistingLombokConstructor(EclipseAST.Node node) { @@ -123,6 +145,22 @@ class PKG { return null; } + static void injectField(EclipseAST.Node type, FieldDeclaration field) { + TypeDeclaration parent = (TypeDeclaration) type.get(); + + if ( parent.fields == null ) { + parent.fields = new FieldDeclaration[1]; + parent.fields[0] = field; + } else { + FieldDeclaration[] newArray = new FieldDeclaration[parent.fields.length + 1]; + System.arraycopy(parent.fields, 0, newArray, 0, parent.fields.length); + newArray[parent.fields.length] = field; + parent.fields = newArray; + } + + type.add(field, Kind.FIELD).recursiveSetHandled(); + } + static void injectMethod(EclipseAST.Node type, AbstractMethodDeclaration method) { TypeDeclaration parent = (TypeDeclaration) type.get(); diff --git a/src/lombok/javac/JavacAST.java b/src/lombok/javac/JavacAST.java index 9e10f320..4c8c2f78 100644 --- a/src/lombok/javac/JavacAST.java +++ b/src/lombok/javac/JavacAST.java @@ -131,7 +131,7 @@ public class JavacAST extends AST<JCTree> { } private Node buildType(JCClassDecl type) { - if ( alreadyHandled(type) ) return null; + if ( setAndGetAsHandled(type) ) return null; List<Node> childNodes = new ArrayList<Node>(); for ( JCTree def : type.defs ) { @@ -152,7 +152,7 @@ public class JavacAST extends AST<JCTree> { } private Node buildField(JCVariableDecl field) { - if ( alreadyHandled(field) ) return null; + if ( setAndGetAsHandled(field) ) return null; List<Node> childNodes = new ArrayList<Node>(); for ( JCAnnotation annotation : field.mods.annotations ) addIfNotNull(childNodes, buildAnnotation(annotation)); addIfNotNull(childNodes, buildExpression(field.init)); @@ -160,7 +160,7 @@ public class JavacAST extends AST<JCTree> { } private Node buildLocalVar(JCVariableDecl local, Kind kind) { - if ( alreadyHandled(local) ) return null; + if ( setAndGetAsHandled(local) ) return null; List<Node> childNodes = new ArrayList<Node>(); for ( JCAnnotation annotation : local.mods.annotations ) addIfNotNull(childNodes, buildAnnotation(annotation)); addIfNotNull(childNodes, buildExpression(local.init)); @@ -168,14 +168,14 @@ public class JavacAST extends AST<JCTree> { } private Node buildInitializer(JCBlock initializer) { - if ( alreadyHandled(initializer) ) return null; + if ( setAndGetAsHandled(initializer) ) return null; List<Node> childNodes = new ArrayList<Node>(); for ( JCStatement statement: initializer.stats ) addIfNotNull(childNodes, buildStatement(statement)); return putInMap(new Node(initializer, childNodes, Kind.INITIALIZER)); } private Node buildMethod(JCMethodDecl method) { - if ( alreadyHandled(method) ) return null; + if ( setAndGetAsHandled(method) ) return null; List<Node> childNodes = new ArrayList<Node>(); for ( JCAnnotation annotation : method.mods.annotations ) addIfNotNull(childNodes, buildAnnotation(annotation)); for ( JCVariableDecl param : method.params ) addIfNotNull(childNodes, buildLocalVar(param, Kind.ARGUMENT)); @@ -185,7 +185,7 @@ public class JavacAST extends AST<JCTree> { } private Node buildAnnotation(JCAnnotation annotation) { - if ( alreadyHandled(annotation) ) return null; + if ( setAndGetAsHandled(annotation) ) return null; return putInMap(new Node(annotation, null, Kind.ANNOTATION)); } @@ -198,15 +198,13 @@ public class JavacAST extends AST<JCTree> { } private Node buildStatementOrExpression(JCTree statement) { - if ( statement == null || alreadyHandled(statement) ) return null; + if ( statement == null ) return null; if ( statement instanceof JCAnnotation ) return null; if ( statement instanceof JCClassDecl ) return buildType((JCClassDecl)statement); if ( statement instanceof JCVariableDecl ) return buildLocalVar((JCVariableDecl)statement, Kind.LOCAL); - //We drill down because LocalDeclarations and TypeDeclarations can occur anywhere, even in, say, - //an if block, or even the expression on an assert statement! + if ( setAndGetAsHandled(statement) ) return null; - setAsHandled(statement); return drill(statement); } |