diff options
author | Roel Spilker <r.spilker@gmail.com> | 2011-05-03 02:25:14 +0200 |
---|---|---|
committer | Roel Spilker <r.spilker@gmail.com> | 2011-05-03 02:25:14 +0200 |
commit | e5e35213780a87c813b892d5efc1288125980baf (patch) | |
tree | 084dd2ef9473ae2ed1b5df1006813e6ccf5661a7 /src | |
parent | 35e18b9332a909aac013697c90d8240826953caf (diff) | |
download | lombok-e5e35213780a87c813b892d5efc1288125980baf.tar.gz lombok-e5e35213780a87c813b892d5efc1288125980baf.tar.bz2 lombok-e5e35213780a87c813b892d5efc1288125980baf.zip |
Eclipse 3.7 updated some internal AST classes, causing:
NoSuchMethodError: CastExpression.<init>
This commit fixes this (now lombok works both <3.7 and 3.7).
fixes issue #206
Diffstat (limited to 'src')
-rw-r--r-- | src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 72 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java | 29 |
2 files changed, 91 insertions, 10 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 860cf44f..a2867c39 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -23,6 +23,8 @@ package lombok.eclipse.handlers; import static lombok.eclipse.Eclipse.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; @@ -32,6 +34,7 @@ import java.util.regex.Pattern; import lombok.AccessLevel; import lombok.Data; import lombok.Getter; +import lombok.Lombok; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; import lombok.core.handlers.TransformationsUtil; @@ -44,6 +47,7 @@ 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.ArrayInitializer; +import org.eclipse.jdt.internal.compiler.ast.CastExpression; import org.eclipse.jdt.internal.compiler.ast.Clinit; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; @@ -63,6 +67,7 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; +import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.ThisReference; @@ -70,6 +75,7 @@ import org.eclipse.jdt.internal.compiler.ast.ThrowStatement; 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.Binding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; /** @@ -655,6 +661,72 @@ public class EclipseHandlerUtil { return problematic; } + /** + * In eclipse 3.7+, the CastExpression constructor was changed from a really weird version to + * a less weird one. Unfortunately that means we need to use reflection as we want to be compatible + * with eclipse versions before 3.7 and 3.7+. + * + * @param ref The {@code foo} in {@code (String)foo}. + * @param castTo The {@code String} in {@code (String)foo}. + */ + public static CastExpression makeCastExpression(Expression ref, TypeReference castTo, ASTNode source) { + CastExpression result; + try { + if (castExpressionConstructorIsTypeRefBased) { + result = castExpressionConstructor.newInstance(ref, castTo); + } else { + Expression castToConverted = castTo; + + if (castTo.getClass() == SingleTypeReference.class && !PRIMITIVE_NAMES.contains( + " " + new String(((SingleTypeReference)castTo).token) + " ")) { + SingleTypeReference str = (SingleTypeReference) castTo; + //Why a SingleNameReference instead of a SingleTypeReference you ask? I don't know. It seems dumb. Ask the ecj guys. + castToConverted = new SingleNameReference(str.token, 0); + castToConverted.bits = (castToConverted.bits & ~Binding.VARIABLE) | Binding.TYPE; + castToConverted.sourceStart = str.sourceStart; + castToConverted.sourceEnd = str.sourceEnd; + Eclipse.setGeneratedBy(castToConverted, source); + } else if (castTo.getClass() == QualifiedTypeReference.class) { + QualifiedTypeReference qtr = (QualifiedTypeReference) castTo; + //Same here, but for the more complex types, they stay types. + castToConverted = new QualifiedNameReference(qtr.tokens, qtr.sourcePositions, qtr.sourceStart, qtr.sourceEnd); + castToConverted.bits = (castToConverted.bits & ~Binding.VARIABLE) | Binding.TYPE; + Eclipse.setGeneratedBy(castToConverted, source); + } + + result = castExpressionConstructor.newInstance(ref, castToConverted); + } + } catch (InvocationTargetException e) { + throw Lombok.sneakyThrow(e.getCause()); + } catch (IllegalAccessException e) { + throw Lombok.sneakyThrow(e); + } catch (InstantiationException e) { + throw Lombok.sneakyThrow(e); + } + + Eclipse.setGeneratedBy(result, source); + return result; + } + + private static final String PRIMITIVE_NAMES = " int long float double char short byte boolean "; + private static final Constructor<CastExpression> castExpressionConstructor; + private static final boolean castExpressionConstructorIsTypeRefBased; + + static { + Constructor<?> constructor = null; + for (Constructor<?> ctor : CastExpression.class.getConstructors()) { + if (ctor.getParameterTypes().length != 2) continue; + constructor = ctor; + } + + @SuppressWarnings("unchecked") + Constructor<CastExpression> constructor_ = (Constructor<CastExpression>) constructor; + castExpressionConstructor = constructor_; + + castExpressionConstructorIsTypeRefBased = + (castExpressionConstructor.getParameterTypes()[1] == TypeReference.class); + } + private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; static Annotation[] getAndRemoveAnnotationParameter(Annotation annotation, String annotationName) { diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index adcb8e6a..8ee7272c 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -510,9 +510,9 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA other.modifiers |= ClassFileConstants.AccFinal; Eclipse.setGeneratedBy(other, source); char[] typeName = typeDecl.name; - Expression targetType; + TypeReference targetType; if (typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0) { - targetType = new SingleNameReference(((TypeDeclaration)type.get()).name, p); + targetType = new SingleTypeReference(typeName, p); Eclipse.setGeneratedBy(targetType, source); other.type = new SingleTypeReference(typeName, p); Eclipse.setGeneratedBy(other.type, source); @@ -530,8 +530,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } NameReference oRef = new SingleNameReference(new char[] { 'o' }, p); Eclipse.setGeneratedBy(oRef, source); - other.initialization = new CastExpression(oRef, targetType); - Eclipse.setGeneratedBy(other.initialization, source); + other.initialization = EclipseHandlerUtil.makeCastExpression(oRef, targetType, source); statements.add(other); } } @@ -547,8 +546,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA ThisReference thisReference = new ThisReference(pS, pE); Eclipse.setGeneratedBy(thisReference, source); - CastExpression castThisRef = new CastExpression(thisReference, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT)); - Eclipse.setGeneratedBy(castThisRef, source); + CastExpression castThisRef = EclipseHandlerUtil.makeCastExpression(thisReference, generateQualifiedTypeRef(source, TypeConstants.JAVA_LANG_OBJECT), source); castThisRef.sourceStart = pS; castThisRef.sourceEnd = pE; otherCanEqual.arguments = new Expression[] {castThisRef}; @@ -625,8 +623,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA equalsCall.receiver = createFieldAccessor(field, fieldAccess, source); equalsCall.selector = "equals".toCharArray(); Expression equalsArg = createFieldAccessor(field, fieldAccess, source, otherName); - CastExpression castEqualsArg = new CastExpression(equalsArg, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT)); - Eclipse.setGeneratedBy(castEqualsArg, source); + CastExpression castEqualsArg = EclipseHandlerUtil.makeCastExpression(equalsArg, generateQualifiedTypeRef(source, TypeConstants.JAVA_LANG_OBJECT), source); castEqualsArg.sourceStart = pS; castEqualsArg.sourceEnd = pE; equalsCall.arguments = new Expression[] { castEqualsArg }; UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT); @@ -762,9 +759,8 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA TypeReference intRef = TypeReference.baseTypeReference(TypeIds.T_int, 0); intRef.sourceStart = pS; intRef.sourceEnd = pE; Eclipse.setGeneratedBy(intRef, source); - CastExpression expr = new CastExpression(xorParts, intRef); + CastExpression expr = EclipseHandlerUtil.makeCastExpression(xorParts, intRef, source); expr.sourceStart = pS; expr.sourceEnd = pE; - Eclipse.setGeneratedBy(expr, source); return expr; } @@ -779,4 +775,17 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(ref, source); return ref; } + + private TypeReference generateQualifiedTypeRef(ASTNode source, char[]... varNames) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + + TypeReference ref; + + long[] poss = Eclipse.poss(source, varNames.length); + if (varNames.length > 1) ref = new QualifiedTypeReference(varNames, poss); + else ref = new SingleTypeReference(varNames[0], p); + Eclipse.setGeneratedBy(ref, source); + return ref; + } } |