diff options
author | Reinier Zwitserloot <reinier@zwitserloot.com> | 2010-11-28 16:52:24 +0100 |
---|---|---|
committer | Reinier Zwitserloot <reinier@zwitserloot.com> | 2010-11-28 16:52:24 +0100 |
commit | 63664a310fb7ae7048a0d58b6fa2fb7affdf147a (patch) | |
tree | 699146d9a12aac7646e5781a684d13652d0b66dc /src | |
parent | 07cfed749e8aa4269fb5060cc3e466c7edb910a4 (diff) | |
download | lombok-63664a310fb7ae7048a0d58b6fa2fb7affdf147a.tar.gz lombok-63664a310fb7ae7048a0d58b6fa2fb7affdf147a.tar.bz2 lombok-63664a310fb7ae7048a0d58b6fa2fb7affdf147a.zip |
bugfixes for typeToJCTree. HandleDelegate (javac) is working better.
Diffstat (limited to 'src')
-rw-r--r-- | src/core/lombok/javac/JavacResolution.java | 29 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleDelegate.java | 122 | ||||
-rw-r--r-- | src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java | 2 |
3 files changed, 133 insertions, 20 deletions
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index b746e673..1200c2b6 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -17,6 +17,7 @@ import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.CapturedType; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.WildcardType; import com.sun.tools.javac.code.TypeTags; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.comp.Attr; @@ -366,26 +367,34 @@ public class JavacResolution { List<Type> ifaces = ((ClassType)type).interfaces_field; Type supertype = ((ClassType)type).supertype_field; if (ifaces != null && ifaces.length() == 1) { - return typeToJCTree(ifaces.get(0), maker, ast, allowCompound); + return typeToJCTree(ifaces.get(0), maker, ast, allowCompound, allowVoid); } - if (supertype != null) return typeToJCTree(supertype, maker, ast, allowCompound); + if (supertype != null) return typeToJCTree(supertype, maker, ast, allowCompound, allowVoid); } throw new TypeNotConvertibleException("Anonymous inner class"); } - if (type instanceof CapturedType) { + if (type instanceof CapturedType || type instanceof WildcardType) { + Type lower, upper; + if (type instanceof WildcardType) { + upper = ((WildcardType)type).getExtendsBound(); + lower = ((WildcardType)type).getSuperBound(); + } else { + lower = type.getLowerBound(); + upper = type.getUpperBound(); + } if (allowCompound) { - if (type.getLowerBound() == null || type.getLowerBound().tag == TypeTags.BOT) { - if (type.getUpperBound().toString().equals("java.lang.Object")) { + if (lower == null || lower.tag == TypeTags.BOT) { + if (upper == null || upper.toString().equals("java.lang.Object")) { return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); } - return maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), typeToJCTree(type.getUpperBound(), maker, ast, false)); + return maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), typeToJCTree(upper, maker, ast, false, false)); } else { - return maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), typeToJCTree(type.getLowerBound(), maker, ast, false)); + return maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), typeToJCTree(lower, maker, ast, false, false)); } } - if (type.getUpperBound() != null) { - return typeToJCTree(type.getUpperBound(), maker, ast, allowCompound); + if (upper != null) { + return typeToJCTree(upper, maker, ast, allowCompound, allowVoid); } return createJavaLangObject(maker, ast); @@ -402,7 +411,7 @@ public class JavacResolution { if (generics != null && !generics.isEmpty()) { ListBuffer<JCExpression> args = ListBuffer.lb(); - for (Type t : generics) args.append(typeToJCTree(t, maker, ast, true)); + for (Type t : generics) args.append(typeToJCTree(t, maker, ast, true, false)); replacement = maker.TypeApply(replacement, args.toList()); } diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java index 73491770..1acbbf8d 100644 --- a/src/core/lombok/javac/handlers/HandleDelegate.java +++ b/src/core/lombok/javac/handlers/HandleDelegate.java @@ -31,9 +31,20 @@ import java.util.Set; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ErrorType; import javax.lang.model.type.ExecutableType; +import javax.lang.model.type.NoType; +import javax.lang.model.type.NullType; +import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.TypeVisitor; +import javax.lang.model.type.WildcardType; import lombok.Delegate; import lombok.core.AST.Kind; @@ -151,11 +162,95 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { } private JCMethodDecl createDelegateMethod(MethodSig sig, JavacNode annotation, Name delegateFieldName) throws TypeNotConvertibleException { - /** public <P1, P2, ...> ReturnType methodName(ParamType1 $p1, ParamType2 $p2, ...) throws T1, T2, ... { - * (return) delegate.<P1, P2>methodName($p1, $p2); + /** public <T, U, ...> ReturnType methodName(ParamType1 name1, ParamType2 name2, ...) throws T1, T2, ... { + * (return) delegate.<T, U>methodName(name1, name2); * } */ + if (!sig.elem.getTypeParameters().isEmpty()) { + // There's a rare but problematic case if a delegate method has its own type variables, and the delegated type does too, and the method uses both. + // If for example the delegated type has <E>, and the method has <T>, but in our class we have a <T> at the class level, then we have two different + // type variables both named 'T'. We detect this situation and error out asking the programmer to rename their type variable. + final Set<String> usedTypeVars = new HashSet<String>(); + class TypeScanner implements TypeVisitor<Void, Void> { + @Override public Void visit(TypeMirror t, Void p) { + return null; + } + + @Override public Void visit(TypeMirror t) { + return null; + } + + @Override public Void visitPrimitive(PrimitiveType t, Void p) { + return null; + } + + @Override public Void visitNull(NullType t, Void p) { + return null; + } + + @Override public Void visitArray(ArrayType t, Void p) { + t.getComponentType().accept(this, null); + return null; + } + + @Override public Void visitDeclared(DeclaredType t, Void p) { + for (TypeMirror arg : t.getTypeArguments()) { + arg.accept(this, null); + } + + return null; + } + + @Override public Void visitError(ErrorType t, Void p) { + return null; + } + + @Override public Void visitTypeVariable(TypeVariable t, Void p) { + String name = t.asElement().getSimpleName().toString(); + usedTypeVars.add(name); + return null; + } + + @Override public Void visitWildcard(WildcardType t, Void p) { + if (t.getExtendsBound() != null) t.getExtendsBound().accept(this, null); + if (t.getSuperBound() != null) t.getSuperBound().accept(this, null); + return null; + } + + @Override public Void visitExecutable(ExecutableType t, Void p) { + return null; + } + + @Override public Void visitNoType(NoType t, Void p) { + return null; + } + + @Override public Void visitUnknown(TypeMirror t, Void p) { + return null; + } + } + + TypeScanner scanner = new TypeScanner(); + + sig.elem.getReturnType().accept(scanner, null); + for (VariableElement param : sig.elem.getParameters()) { + param.asType().accept(scanner, null); + } + for (TypeMirror ex : sig.elem.getThrownTypes()) { + ex.accept(scanner, null); + } + + for (TypeParameterElement ownVar : sig.elem.getTypeParameters()) { + usedTypeVars.remove(ownVar.toString()); + } + + if (!usedTypeVars.isEmpty()) { + + + } + } + TreeMaker maker = annotation.getTreeMaker(); com.sun.tools.javac.util.List<JCAnnotation> annotations; @@ -177,9 +272,8 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { ListBuffer<JCExpression> typeArgs = sig.type.getTypeVariables().isEmpty() ? null : new ListBuffer<JCExpression>(); Types types = Types.instance(annotation.getContext()); - int nameCounter = 0; for (TypeMirror param : sig.type.getTypeVariables()) { - Name name = annotation.toName("P" + (nameCounter++)); + Name name = ((TypeVar) param).tsym.name; typeParams.append(maker.TypeParameter(name, maker.Types(types.getBounds((TypeVar) param)))); typeArgs.append(maker.Ident(name)); } @@ -188,10 +282,11 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { thrown.append(JavacResolution.typeToJCTree((Type) ex, maker, annotation.getAst(), true)); } - nameCounter = 0; + int idx = 0; for (TypeMirror param : sig.type.getParameterTypes()) { - Name name = annotation.toName("$a" + (nameCounter++)); JCModifiers paramMods = maker.Modifiers(Flags.FINAL); + String[] paramNames = sig.getParameterNames(); + Name name = annotation.toName(paramNames[idx++]); params.append(maker.VarDef(paramMods, name, JavacResolution.typeToJCTree((Type) param, maker, annotation.getAst(), true), null)); args.append(maker.Ident(name)); } @@ -222,7 +317,7 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { String sig = printSig(methodType, member.name, node.getTypesUtil()); if (!banList.add(sig)) continue; //If add returns false, it was already in there boolean isDeprecated = exElem.getAnnotation(Deprecated.class) != null; - signatures.add(new MethodSig(member.name, methodType, isDeprecated)); + signatures.add(new MethodSig(member.name, methodType, isDeprecated, exElem)); } if (ct.supertype_field instanceof ClassType) addMethodBindings(signatures, (ClassType) ct.supertype_field, node, banList); @@ -235,11 +330,22 @@ public class HandleDelegate implements JavacAnnotationHandler<Delegate> { final Name name; final ExecutableType type; final boolean isDeprecated; + final ExecutableElement elem; - MethodSig(Name name, ExecutableType type, boolean isDeprecated) { + MethodSig(Name name, ExecutableType type, boolean isDeprecated, ExecutableElement elem) { this.name = name; this.type = type; this.isDeprecated = isDeprecated; + this.elem = elem; + } + + String[] getParameterNames() { + List<? extends VariableElement> paramList = elem.getParameters(); + String[] paramNames = new String[paramList.size()]; + for (int i = 0; i < paramNames.length; i++) { + paramNames[i] = paramList.get(i).getSimpleName().toString(); + } + return paramNames; } @Override public String toString() { diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java index c7da502e..6198335c 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java @@ -26,7 +26,6 @@ import static lombok.eclipse.Eclipse.*; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -72,7 +71,6 @@ import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; -import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; public class PatchDelegate { static void addPatches(ScriptManager sm, boolean ecj) { |