diff options
author | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-20 23:46:17 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-21 00:10:58 +0200 |
commit | 255bd5907176cb5d2c4fb1cf6a9b48b14af0b4ba (patch) | |
tree | 347c4b1cf5b34b3975cc00e26a42c75ee1295b76 /src/lombok/eclipse/handlers | |
parent | 2e8e43a12e21151ff470a2729373b4af4980d113 (diff) | |
download | lombok-255bd5907176cb5d2c4fb1cf6a9b48b14af0b4ba.tar.gz lombok-255bd5907176cb5d2c4fb1cf6a9b48b14af0b4ba.tar.bz2 lombok-255bd5907176cb5d2c4fb1cf6a9b48b14af0b4ba.zip |
Due to a java bug, constants in enums don't work, so instead the default access level for @Getter and @Setter have now just been hardcoded in GetterHandler and SetterHandler.
Added ability to look up the Node object for any given AST object on Node itself, as you don't usually have the AST object.
Added toString() method generating to @Data, and this required some fancy footwork in finding if we've already generated methods, and editing a generated method to fill in binding and type resolutions. HandleGetter and HandleSetter have been updated to use these features.
Exceptions caused by lombok handlers show up in the eclipse error log, but now, if they are related to a CompilationUnit, also as a problem (error) on the CUD - those error log entries are easy to miss!
Our ASTs can now be appended to. When you generate a new AST node, you should add it to the AST, obviously. Getter/Setter have been updated to use this.
Diffstat (limited to 'src/lombok/eclipse/handlers')
-rw-r--r-- | src/lombok/eclipse/handlers/HandleData.java | 127 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleGetter.java | 66 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleSetter.java | 92 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/PKG.java | 64 |
4 files changed, 278 insertions, 71 deletions
diff --git a/src/lombok/eclipse/handlers/HandleData.java b/src/lombok/eclipse/handlers/HandleData.java index 64540e95..6c77644f 100644 --- a/src/lombok/eclipse/handlers/HandleData.java +++ b/src/lombok/eclipse/handlers/HandleData.java @@ -1,20 +1,38 @@ package lombok.eclipse.handlers; +import static lombok.eclipse.handlers.PKG.*; + import java.util.ArrayList; +import java.util.Collection; import java.util.List; -import org.eclipse.jdt.internal.compiler.ast.Annotation; -import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.mangosdk.spi.ProviderFor; - +import lombok.AccessLevel; import lombok.Data; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseAST.Node; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.OperatorIds; +import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; +import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; +import org.eclipse.jdt.internal.compiler.ast.Statement; +import org.eclipse.jdt.internal.compiler.ast.StringLiteral; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.mangosdk.spi.ProviderFor; + @ProviderFor(EclipseAnnotationHandler.class) public class HandleData implements EclipseAnnotationHandler<Data> { @Override public boolean handle(AnnotationValues<Data> annotation, Annotation ast, Node annotationNode) { @@ -32,18 +50,111 @@ public class HandleData implements EclipseAnnotationHandler<Data> { } List<Node> nodesForEquality = new ArrayList<Node>(); + List<Node> nodesForConstructorAndToString = new ArrayList<Node>(); for ( Node child : typeNode.down() ) { if ( child.getKind() != Kind.FIELD ) continue; FieldDeclaration fieldDecl = (FieldDeclaration) child.get(); //Skip static fields. if ( (fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0 ) continue; if ( (fieldDecl.modifiers & ClassFileConstants.AccTransient) == 0 ) nodesForEquality.add(child); + nodesForConstructorAndToString.add(child); new HandleGetter().generateGetterForField(child, annotationNode.get()); if ( (fieldDecl.modifiers & ClassFileConstants.AccFinal) == 0 ) new HandleSetter().generateSetterForField(child, annotationNode.get()); } - //TODO generate constructor, hashCode, equals, toString. - return true; + switch ( methodExists("toString", typeNode) ) { + case NOT_EXISTS: + MethodDeclaration toString = createToString(typeNode, nodesForConstructorAndToString, ast); + injectMethod(typeNode, toString); + break; + case EXISTS_BY_LOMBOK: + injectScopeIntoToString((MethodDeclaration) getExistingLombokMethod("toString", typeNode).get(), typeDecl); + } + + //TODO generate constructor, hashCode, equals. + return false; + } + + private void injectScopeIntoToString(MethodDeclaration method, TypeDeclaration typeDecl) { + if ( typeDecl.scope != null ) { + method.scope = new MethodScope(typeDecl.scope, method, false); + method.returnType.resolvedType = typeDecl.scope.getJavaLangString(); + method.binding = new MethodBinding(method.modifiers, + method.selector, typeDecl.scope.getJavaLangString(), null, null, typeDecl.binding); + } + } + + private MethodDeclaration createToString(Node type, Collection<Node> fields, ASTNode pos) { + char[] rawTypeName = ((TypeDeclaration)type.get()).name; + String typeName = rawTypeName == null ? "" : new String(rawTypeName); + char[] prefix = (typeName + "(").toCharArray(); + char[] suffix = ")".toCharArray(); + char[] infix = ", ".toCharArray(); + long p = (long)pos.sourceStart << 32 | pos.sourceEnd; + final int PLUS = OperatorIds.PLUS; + + boolean first = true; + Expression current = new StringLiteral(prefix, 0, 0, 0); + for ( Node field : fields ) { + char[] fName = ((FieldDeclaration)field.get()).name; + if ( fName == null ) continue; + if ( !first ) { + current = new BinaryExpression(current, new StringLiteral(infix, 0, 0, 0), PLUS); + } + else first = false; + current = new BinaryExpression(current, new SingleNameReference(fName, p), PLUS); + } + current = new BinaryExpression(current, new StringLiteral(suffix, 0, 0, 0), PLUS); + + ReturnStatement returnStatement = new ReturnStatement(current, (int)(p >> 32), (int)p); + + MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); + method.modifiers = PKG.toModifier(AccessLevel.PUBLIC); + method.returnType = Eclipse.TYPEREF_JAVA_LANG_STRING; + method.annotations = null; + method.arguments = null; + method.selector = "toString".toCharArray(); + method.binding = null; + method.thrownExceptions = null; + method.typeParameters = null; + injectScopeIntoToString(method, (TypeDeclaration) type.get()); + method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + method.bodyStart = method.declarationSourceStart = method.sourceStart = pos.sourceStart; + method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = pos.sourceEnd; + method.statements = new Statement[] { returnStatement }; + return method; + } + + private MethodDeclaration createEquals(Collection<Node> fields) { + return null; + } + + private ConstructorDeclaration createConstructor(Collection<Node> fields) { + //If using an of() constructor, make private. + //method params + //on loop: Assignment(FieldReference(ThisReference, "x"), SingleNameReference("x")) + return null; + } + + private MethodDeclaration createStaticConstructor(Collection<Node> fields) { + //Return(AllocationExpression(SingleTypeReference("Bar"), namesOfFields); + return null; + } + + private MethodDeclaration createHashCode(Collection<Node> fields) { + //booleans: conditionalexpression that bounces between 1231 and 1237. + //longs: (int) (lng ^ (lng >>> 32)); + //doubles and floats: Double.doubleToLongBits, then as long. + + //local final var PRIME = IntLiteral(primeNumber) + //local final var RESULT = IntLiteral(1) + + // Assignment("RESULT", BinaryExpression("+", BinaryExpression("*", "PRIME", "RESULT"), "name") + + // add = ConditionalExpression(EqualExpression("name", NullLiteral), IntLiteral(0), MessageSend("name", "hashCode()")) + // Assignment("RESULT", BinaryExpression("+", BinaryExpression("*", "PRIME", "RESULT"), add); + + return null; } } diff --git a/src/lombok/eclipse/handlers/HandleGetter.java b/src/lombok/eclipse/handlers/HandleGetter.java index 798705da..5b3fbf90 100644 --- a/src/lombok/eclipse/handlers/HandleGetter.java +++ b/src/lombok/eclipse/handlers/HandleGetter.java @@ -1,18 +1,17 @@ package lombok.eclipse.handlers; import static lombok.eclipse.handlers.PKG.*; - import lombok.AccessLevel; import lombok.Getter; import lombok.core.AnnotationValues; import lombok.core.TransformationsUtil; import lombok.core.AST.Kind; import lombok.eclipse.Eclipse; +import lombok.eclipse.EclipseASTVisitor; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseAST.Node; 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.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; @@ -23,14 +22,16 @@ import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.mangosdk.spi.ProviderFor; @ProviderFor(EclipseAnnotationHandler.class) public class HandleGetter implements EclipseAnnotationHandler<Getter> { public void generateGetterForField(Node fieldNode, ASTNode pos) { - AccessLevel level = Getter.DEFAULT_ACCESS_LEVEL; + AccessLevel level = AccessLevel.PUBLIC; Node errorNode = fieldNode; + boolean whineIfExists = false; for ( Node child : fieldNode.down() ) { if ( child.getKind() == Kind.ANNOTATION ) { @@ -38,21 +39,22 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { level = Eclipse.createAnnotation(Getter.class, child).getInstance().value(); errorNode = child; pos = child.get(); + whineIfExists = true; break; } } } - createGetterForField(level, fieldNode, errorNode, pos); + createGetterForField(level, fieldNode, errorNode, pos, whineIfExists); } @Override public boolean handle(AnnotationValues<Getter> annotation, Annotation ast, Node annotationNode) { Node fieldNode = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); - return createGetterForField(level, fieldNode, annotationNode, annotationNode.get()); + return createGetterForField(level, fieldNode, annotationNode, annotationNode.get(), true); } - private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos) { + private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos, boolean whineIfExists) { if ( fieldNode.getKind() != Kind.FIELD ) { errorNode.addError("@Getter is only supported on a field."); return false; @@ -63,30 +65,40 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { String getterName = TransformationsUtil.toGetterName( new String(field.name), nameEquals(fieldType.getTypeName(), "boolean")); - TypeDeclaration parent = (TypeDeclaration) fieldNode.up().get(); - if ( parent.methods != null ) for ( AbstractMethodDeclaration method : parent.methods ) { - if ( method.selector != null && new String(method.selector).equals(getterName) ) { - errorNode.addWarning(String.format( - "Not generating %s(): A method with that name already exists", getterName)); - return false; - } + int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); + + switch ( methodExists(getterName, fieldNode) ) { + case EXISTS_BY_LOMBOK: + Node methodNode = getExistingLombokMethod(getterName, fieldNode); + injectScopeIntoGetter(modifier, field, (MethodDeclaration)methodNode.get(), (TypeDeclaration) methodNode.up().get()); + return false; + case EXISTS_BY_USER: + if ( whineIfExists ) errorNode.addWarning( + String.format("Not generating %s(): A method with that name already exists", getterName)); + return false; + default: + case NOT_EXISTS: + //continue with creating the getter } - int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); + if ( new String(field.name).equals("a") ) fieldNode.up().traverse(new EclipseASTVisitor.Printer()); + MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), field, getterName, modifier, pos); - MethodDeclaration method = generateGetter(parent, field, getterName, modifier, pos); + injectMethod(fieldNode.up(), method); - if ( parent.methods == null ) { - parent.methods = new AbstractMethodDeclaration[1]; - parent.methods[0] = method; - } else { - AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1]; - System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length); - newArray[parent.methods.length] = method; - parent.methods = newArray; + return false; + } + + private void injectScopeIntoGetter(int modifier, FieldDeclaration field, MethodDeclaration method, TypeDeclaration parent) { + if ( parent.scope != null ) { + if ( method.binding != null ) { + method.binding.returnType = field.type.resolvedType; + } else { + method.scope = new MethodScope(parent.scope, method, false); + method.returnType.resolvedType = field.type.resolvedType; + method.binding = new MethodBinding(modifier, method.selector, method.returnType.resolvedType, null, null, parent.binding); + } } - - return true; } private MethodDeclaration generateGetter(TypeDeclaration parent, FieldDeclaration field, String name, @@ -100,8 +112,8 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { method.binding = null; method.thrownExceptions = null; method.typeParameters = null; - method.scope = parent.scope == null ? null : new MethodScope(parent.scope, method, false); - method.bits |= ASTNode.Bit24; + injectScopeIntoGetter(modifier, field, method, parent); + method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; Expression fieldExpression = new SingleNameReference(field.name, (field.declarationSourceStart << 32) | field.declarationSourceEnd); Statement returnStatement = new ReturnStatement(fieldExpression, field.sourceStart, field.sourceEnd); method.bodyStart = method.declarationSourceStart = method.sourceStart = pos.sourceStart; diff --git a/src/lombok/eclipse/handlers/HandleSetter.java b/src/lombok/eclipse/handlers/HandleSetter.java index d0d0d902..c5f87a93 100644 --- a/src/lombok/eclipse/handlers/HandleSetter.java +++ b/src/lombok/eclipse/handlers/HandleSetter.java @@ -1,9 +1,16 @@ package lombok.eclipse.handlers; import static lombok.eclipse.handlers.PKG.*; +import lombok.AccessLevel; +import lombok.Setter; +import lombok.core.AnnotationValues; +import lombok.core.TransformationsUtil; +import lombok.core.AST.Kind; +import lombok.eclipse.Eclipse; +import lombok.eclipse.EclipseAnnotationHandler; +import lombok.eclipse.EclipseAST.Node; 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.Assignment; @@ -16,24 +23,19 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.mangosdk.spi.ProviderFor; -import lombok.AccessLevel; -import lombok.Setter; -import lombok.core.AnnotationValues; -import lombok.core.TransformationsUtil; -import lombok.core.AST.Kind; -import lombok.eclipse.Eclipse; -import lombok.eclipse.EclipseAnnotationHandler; -import lombok.eclipse.EclipseAST.Node; - @ProviderFor(EclipseAnnotationHandler.class) public class HandleSetter implements EclipseAnnotationHandler<Setter> { public void generateSetterForField(Node fieldNode, ASTNode pos) { - AccessLevel level = Setter.DEFAULT_ACCESS_LEVEL; + AccessLevel level = AccessLevel.PUBLIC; Node errorNode = fieldNode; + boolean whineIfExists = false; for ( Node child : fieldNode.down() ) { if ( child.getKind() == Kind.ANNOTATION ) { @@ -41,51 +43,68 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { level = Eclipse.createAnnotation(Setter.class, child).getInstance().value(); errorNode = child; pos = child.get(); + whineIfExists = true; break; } } } - createSetterForField(level, fieldNode, errorNode, pos); + createSetterForField(level, fieldNode, errorNode, pos, whineIfExists); } @Override public boolean handle(AnnotationValues<Setter> annotation, Annotation ast, Node annotationNode) { Node fieldNode = annotationNode.up(); if ( fieldNode.getKind() != Kind.FIELD ) return false; AccessLevel level = annotation.getInstance().value(); - return createSetterForField(level, fieldNode, annotationNode, annotationNode.get()); + return createSetterForField(level, fieldNode, annotationNode, annotationNode.get(), true); } - private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos) { - if ( fieldNode.getKind() != Kind.FIELD ) return false; + private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos, boolean whineIfExists) { + if ( fieldNode.getKind() != Kind.FIELD ) { + errorNode.addError("@Setter is only supported on a field."); + return false; + } + FieldDeclaration field = (FieldDeclaration) fieldNode.get(); String setterName = TransformationsUtil.toSetterName(new String(field.name)); - TypeDeclaration parent = (TypeDeclaration) fieldNode.up().get(); - if ( parent.methods != null ) for ( AbstractMethodDeclaration method : parent.methods ) { - if ( method.selector != null && new String(method.selector).equals(setterName) ) { - errorNode.addWarning(String.format( - "Not generating %s(%s %s): A method with that name already exists", - setterName, field.type, new String(field.name))); - return false; - } + int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); + + switch ( methodExists(setterName, fieldNode) ) { + case EXISTS_BY_LOMBOK: + Node methodNode = getExistingLombokMethod(setterName, fieldNode); + injectScopeIntoSetter(modifier, field, (MethodDeclaration)methodNode.get(), (TypeDeclaration) methodNode.up().get()); + return false; + case EXISTS_BY_USER: + if ( whineIfExists ) errorNode.addWarning( + String.format("Not generating %s(%s %s): A method with that name already exists", + setterName, field.type, new String(field.name))); + return false; + default: + case NOT_EXISTS: + //continue with creating the setter } - int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); - MethodDeclaration method = generateSetter(parent, field, setterName, modifier, pos); + MethodDeclaration method = generateSetter((TypeDeclaration) fieldNode.up().get(), field, setterName, modifier, pos); - if ( parent.methods == null ) { - parent.methods = new AbstractMethodDeclaration[1]; - parent.methods[0] = method; - } else { - AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1]; - System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length); - newArray[parent.methods.length] = method; - parent.methods = newArray; - } + injectMethod(fieldNode.up(), method); - return true; + return false; + } + + private void injectScopeIntoSetter(int modifier, FieldDeclaration field, MethodDeclaration method, TypeDeclaration parent) { + if ( parent.scope != null ) { + TypeBinding[] params = new TypeBinding[] { field.type.resolvedType }; + + if ( method.binding == null ) { + method.scope = new MethodScope(parent.scope, method, false); + method.binding = new MethodBinding(modifier, method.selector, BaseTypeBinding.VOID, params, null, parent.binding); + } + method.binding.parameters = params; + method.binding.returnType = BaseTypeBinding.VOID; + method.returnType.resolvedType = BaseTypeBinding.VOID; + } } private MethodDeclaration generateSetter(TypeDeclaration parent, FieldDeclaration field, String name, @@ -102,7 +121,8 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { method.thrownExceptions = null; method.typeParameters = null; method.scope = parent.scope == null ? null : new MethodScope(parent.scope, method, false); - method.bits |= ASTNode.Bit24; + method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + injectScopeIntoSetter(modifier, field, method, parent); FieldReference thisX = new FieldReference(("this." + new String(field.name)).toCharArray(), pos); thisX.receiver = new ThisReference(ast.sourceStart, ast.sourceEnd); thisX.token = field.name; diff --git a/src/lombok/eclipse/handlers/PKG.java b/src/lombok/eclipse/handlers/PKG.java index 61f71140..d93807a7 100644 --- a/src/lombok/eclipse/handlers/PKG.java +++ b/src/lombok/eclipse/handlers/PKG.java @@ -3,6 +3,11 @@ package lombok.eclipse.handlers; import java.lang.reflect.Modifier; import lombok.AccessLevel; +import lombok.core.AST.Kind; +import lombok.eclipse.EclipseAST; + +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; class PKG { private PKG() {} @@ -33,4 +38,63 @@ class PKG { return string.contentEquals(sb); } + + enum MethodExistsResult { + NOT_EXISTS, EXISTS_BY_USER, EXISTS_BY_LOMBOK; + } + + static MethodExistsResult methodExists(String methodName, EclipseAST.Node node) { + while ( node != null && !(node.get() instanceof TypeDeclaration) ) { + node = node.up(); + } + + if ( node.get() instanceof TypeDeclaration ) { + TypeDeclaration typeDecl = (TypeDeclaration)node.get(); + if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) { + char[] mName = ((AbstractMethodDeclaration)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; + } + } + } + + return MethodExistsResult.NOT_EXISTS; + } + + static EclipseAST.Node getExistingLombokMethod(String methodName, EclipseAST.Node node) { + while ( node != null && !(node.get() instanceof TypeDeclaration) ) { + node = node.up(); + } + + if ( node.get() instanceof TypeDeclaration ) { + for ( AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods ) { + char[] mName = ((AbstractMethodDeclaration)def).selector; + if ( mName == null ) continue; + if ( methodName.equals(new String(mName)) ) { + EclipseAST.Node existing = node.getNodeFor(def); + if ( existing.isHandled() ) return existing; + } + } + } + + return null; + } + + static void injectMethod(EclipseAST.Node type, AbstractMethodDeclaration method) { + TypeDeclaration parent = (TypeDeclaration) type.get(); + if ( parent.methods == null ) { + parent.methods = new AbstractMethodDeclaration[1]; + parent.methods[0] = method; + } else { + AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1]; + System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length); + newArray[parent.methods.length] = method; + parent.methods = newArray; + } + + type.add(method, Kind.METHOD).recursiveSetHandled(); + } } |