diff options
author | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-23 06:01:13 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-23 06:01:13 +0200 |
commit | 6c82a3c780539825157f721fcfe1a8894e73b161 (patch) | |
tree | f98ea3a9f826d40f0351f3752b1d96596d0fd10d | |
parent | 4ee8e7a3d2513420e0f7affcca61d916c2a7374b (diff) | |
download | lombok-6c82a3c780539825157f721fcfe1a8894e73b161.tar.gz lombok-6c82a3c780539825157f721fcfe1a8894e73b161.tar.bz2 lombok-6c82a3c780539825157f721fcfe1a8894e73b161.zip |
This is a 3-day bughunt that ended up being something extremely simple:
** DO NOT REUSE TYPEREFERENCE OBJECTS **
because that makes the binding process go pearshaped - after hte first run, that TypeReference object's binding parameter is set, and as its set, the resolver won't bother re-resolving it.
However, each parse run starts with new scope objects, and any 2 bindings created by different scopes aren't equal to each other. urrrrrrgh!
Fortunately, a lot of code that 'fixed' methods by adding bindings and scope have all been removed, as the parser patch point is well before these bindings are created. Thus:
** NEVER CREATE YOUR OWN BINDINGS AND SCOPE OBJECTS **
because if it comes down to that, you're doing it entirely wrong. That's eclipse's job. We're patching where we are so you don't have to do this.
-rw-r--r-- | src/lombok/eclipse/Eclipse.java | 4 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleData.java | 62 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleGetter.java | 21 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleSetter.java | 22 |
4 files changed, 30 insertions, 79 deletions
diff --git a/src/lombok/eclipse/Eclipse.java b/src/lombok/eclipse/Eclipse.java index a7286058..8457e28a 100644 --- a/src/lombok/eclipse/Eclipse.java +++ b/src/lombok/eclipse/Eclipse.java @@ -28,10 +28,8 @@ import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.Literal; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; -import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.osgi.framework.Bundle; @@ -42,8 +40,6 @@ public class Eclipse { } private static final String DEFAULT_BUNDLE = "org.eclipse.jdt.core"; - public static final TypeReference TYPEREF_JAVA_LANG_STRING = new QualifiedTypeReference( - TypeConstants.JAVA_LANG_STRING, new long[] {0, 0, 0}); public static void error(CompilationUnitDeclaration cud, String message) { error(cud, message, DEFAULT_BUNDLE, null); diff --git a/src/lombok/eclipse/handlers/HandleData.java b/src/lombok/eclipse/handlers/HandleData.java index b4bba7d7..dd398d74 100644 --- a/src/lombok/eclipse/handlers/HandleData.java +++ b/src/lombok/eclipse/handlers/HandleData.java @@ -2,8 +2,10 @@ package lombok.eclipse.handlers; import static lombok.eclipse.handlers.PKG.*; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import lombok.AccessLevel; @@ -15,6 +17,8 @@ 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.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; @@ -28,6 +32,7 @@ import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; +import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; @@ -35,10 +40,14 @@ import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import org.eclipse.jdt.internal.compiler.ast.TypeParameter; 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.TypeConstants; +import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.mangosdk.spi.ProviderFor; @ProviderFor(EclipseAnnotationHandler.class) @@ -76,9 +85,11 @@ public class HandleData implements EclipseAnnotationHandler<Data> { case NOT_EXISTS: MethodDeclaration toString = createToString(typeNode, nodesForConstructorAndToString, ast); injectMethod(typeNode, toString); - break; + //fallthrough case EXISTS_BY_LOMBOK: - injectScopeIntoToString((MethodDeclaration) getExistingLombokMethod("toString", typeNode).get(), typeDecl); +// TypeBinding javaLangString = null; +// if ( typeDecl.scope != null ) javaLangString = typeDecl.scope.getJavaLangString(); +// fixMethodBinding(getExistingLombokMethod("toString", typeNode), javaLangString, Collections.<Node>emptyList()); } switch ( constructorExists(typeNode) ) { @@ -86,7 +97,12 @@ public class HandleData implements EclipseAnnotationHandler<Data> { ConstructorDeclaration constructor = createConstructor( ann.staticConstructor().isEmpty(), typeNode, nodesForConstructorAndToString, ast); injectMethod(typeNode, constructor); - break; + //fallthrough + case EXISTS_BY_LOMBOK: +// constructor = createConstructor( +// ann.staticConstructor().isEmpty(), typeNode, nodesForConstructorAndToString, ast); +// injectScopeIntoConstructor(constructor, nodesForConstructorAndToString, typeDecl); +// fixMethodBinding(getExistingLombokConstructor(typeNode), typeDecl.binding, nodesForConstructorAndToString); } if ( !ann.staticConstructor().isEmpty() ) { @@ -95,11 +111,12 @@ public class HandleData implements EclipseAnnotationHandler<Data> { MethodDeclaration staticConstructor = createStaticConstructor( ann.staticConstructor(), typeNode, nodesForConstructorAndToString, ast); injectMethod(typeNode, staticConstructor); - break; + //fallthrough case EXISTS_BY_LOMBOK: - injectScopeIntoStaticConstructor((MethodDeclaration) getExistingLombokMethod( - ann.staticConstructor(), typeNode).get(), - nodesForConstructorAndToString, typeDecl); +// fixMethodBinding(getExistingLombokMethod(ann.staticConstructor(), typeNode), typeDecl.binding, nodesForConstructorAndToString); +// injectScopeIntoStaticConstructor((MethodDeclaration) getExistingLombokMethod( +// ann.staticConstructor(), typeNode).get(), +// nodesForConstructorAndToString, typeDecl); } } @@ -107,15 +124,6 @@ public class HandleData implements EclipseAnnotationHandler<Data> { 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); @@ -142,14 +150,12 @@ public class HandleData implements EclipseAnnotationHandler<Data> { MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); method.modifiers = PKG.toModifier(AccessLevel.PUBLIC); - method.returnType = Eclipse.TYPEREF_JAVA_LANG_STRING; + method.returnType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {0, 0, 0}); 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; @@ -192,32 +198,18 @@ public class HandleData implements EclipseAnnotationHandler<Data> { return constructor; } - private void injectScopeIntoStaticConstructor(MethodDeclaration constructor, Collection<Node> fields, TypeDeclaration typeDecl) { - if ( typeDecl.scope != null ) { - constructor.scope = new MethodScope(typeDecl.scope, constructor, false); -// constructor.binding = new MethodBinding(constructor.modifiers, -// constructor.selector, null, null, null, typeDecl.binding); - constructor.returnType.resolvedType = typeDecl.binding; -// TypeBinding[] bindings = new TypeBinding[fields.size()]; -// int idx = 0; -// for ( Node field : fields ) bindings[idx++] = ((FieldDeclaration)field.get()).type.resolvedType; -// constructor.binding.parameters = bindings; - } - } - private MethodDeclaration createStaticConstructor(String name, Node type, Collection<Node> fields, ASTNode pos) { long p = (long)pos.sourceStart << 32 | pos.sourceEnd; MethodDeclaration constructor = new MethodDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); - constructor.modifiers = PKG.toModifier(AccessLevel.PUBLIC); + constructor.modifiers = PKG.toModifier(AccessLevel.PUBLIC) | Modifier.STATIC; constructor.returnType = new SingleTypeReference(((TypeDeclaration)type.get()).name, p); constructor.annotations = null; constructor.selector = name.toCharArray(); constructor.thrownExceptions = null; constructor.typeParameters = null; - injectScopeIntoStaticConstructor(constructor, fields, (TypeDeclaration) type.get()); constructor.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = pos.sourceStart; constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = pos.sourceEnd; @@ -236,7 +228,7 @@ public class HandleData implements EclipseAnnotationHandler<Data> { statement.arguments = assigns.toArray(new Expression[assigns.size()]); constructor.arguments = args.toArray(new Argument[args.size()]); - constructor.statements = new Statement[] { statement }; + constructor.statements = new Statement[] { new ReturnStatement(statement, (int)(p >> 32), (int)p) }; return constructor; } diff --git a/src/lombok/eclipse/handlers/HandleGetter.java b/src/lombok/eclipse/handlers/HandleGetter.java index 5b3fbf90..d0ec673d 100644 --- a/src/lombok/eclipse/handlers/HandleGetter.java +++ b/src/lombok/eclipse/handlers/HandleGetter.java @@ -22,8 +22,6 @@ 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) @@ -69,9 +67,7 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { 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; + return true; case EXISTS_BY_USER: if ( whineIfExists ) errorNode.addWarning( String.format("Not generating %s(): A method with that name already exists", getterName)); @@ -86,19 +82,7 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { injectMethod(fieldNode.up(), method); - 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, @@ -112,7 +96,6 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { method.binding = null; method.thrownExceptions = null; method.typeParameters = null; - 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); diff --git a/src/lombok/eclipse/handlers/HandleSetter.java b/src/lombok/eclipse/handlers/HandleSetter.java index c5f87a93..d33594b1 100644 --- a/src/lombok/eclipse/handlers/HandleSetter.java +++ b/src/lombok/eclipse/handlers/HandleSetter.java @@ -23,10 +23,7 @@ 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; @@ -72,9 +69,7 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { 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; + return true; case EXISTS_BY_USER: if ( whineIfExists ) errorNode.addWarning( String.format("Not generating %s(%s %s): A method with that name already exists", @@ -93,20 +88,6 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { 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, int modifier, ASTNode ast) { long pos = (((long)ast.sourceStart) << 32) | ast.sourceEnd; @@ -122,7 +103,6 @@ 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; - 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; |