From 6c82a3c780539825157f721fcfe1a8894e73b161 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 23 Jun 2009 06:01:13 +0200 Subject: 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. --- src/lombok/eclipse/handlers/HandleData.java | 62 ++++++++++++--------------- src/lombok/eclipse/handlers/HandleGetter.java | 21 +-------- src/lombok/eclipse/handlers/HandleSetter.java | 22 +--------- 3 files changed, 30 insertions(+), 75 deletions(-) (limited to 'src/lombok/eclipse/handlers') 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 { 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.emptyList()); } switch ( constructorExists(typeNode) ) { @@ -86,7 +97,12 @@ public class HandleData implements EclipseAnnotationHandler { 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 { 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 { 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 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 { 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 { return constructor; } - private void injectScopeIntoStaticConstructor(MethodDeclaration constructor, Collection 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 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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; -- cgit