aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2012-02-14 16:31:48 +0100
committerReinier Zwitserloot <reinier@zwitserloot.com>2012-02-14 16:31:48 +0100
commitf259af306ff97acfcfed2dbfa2e9d4320079d69d (patch)
treec148411a3470cd92ffccb3c6010bc60cf5cc2405
parent653104aa4e61672af91fb23367d9ab3f328a2b89 (diff)
downloadlombok-f259af306ff97acfcfed2dbfa2e9d4320079d69d.tar.gz
lombok-f259af306ff97acfcfed2dbfa2e9d4320079d69d.tar.bz2
lombok-f259af306ff97acfcfed2dbfa2e9d4320079d69d.zip
'val' now works for member types whose outers have generics. (issue #343)
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java55
-rw-r--r--src/core/lombok/javac/JavacResolution.java65
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleVal.java14
-rw-r--r--test/core/src/lombok/AbstractRunTests.java3
5 files changed, 95 insertions, 48 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index c6d7eb41..0bc3cde2 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -30,6 +30,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -562,10 +563,38 @@ public class EclipseHandlerUtil {
}
}
+ // Keep moving up via 'binding.enclosingType()' and gather generics from each binding. We stop after a local type, or a static type, or a top-level type.
+ // Finally, add however many nullTypeArgument[] arrays as that are missing, inverse the list, toArray it, and use that as PTR's typeArgument argument.
+
+ List<TypeReference[]> params = new ArrayList<TypeReference[]>();
+ /* Calculate generics */ {
+ TypeBinding b = binding;
+ while (true) {
+ boolean isFinalStop = b.isLocalType() || !b.isMemberType() || b.enclosingType() == null;
+
+ TypeReference[] tyParams = null;
+ if (b instanceof ParameterizedTypeBinding) {
+ ParameterizedTypeBinding paramized = (ParameterizedTypeBinding) b;
+ if (paramized.arguments != null) {
+ tyParams = new TypeReference[paramized.arguments.length];
+ for (int i = 0; i < tyParams.length; i++) {
+ tyParams[i] = makeType(paramized.arguments[i], pos, true);
+ }
+ }
+ }
+
+ params.add(tyParams);
+ if (isFinalStop) break;
+ b = b.enclosingType();
+ }
+ }
+
char[][] parts;
- if (binding.isLocalType() || binding.isTypeVariable()) {
+ if (binding.isTypeVariable()) {
parts = new char[][] { binding.shortReadableName() };
+ } else if (binding.isLocalType()) {
+ parts = new char[][] { binding.sourceName() };
} else {
String[] pkg = new String(binding.qualifiedPackageName()).split("\\.");
String[] name = new String(binding.qualifiedSourceName()).split("\\.");
@@ -576,27 +605,25 @@ public class EclipseHandlerUtil {
for (; ptr < pkg.length + name.length; ptr++) parts[ptr] = name[ptr - pkg.length].toCharArray();
}
- TypeReference[] params = new TypeReference[0];
+ while (params.size() < parts.length) params.add(null);
+ Collections.reverse(params);
- if (binding instanceof ParameterizedTypeBinding) {
- ParameterizedTypeBinding paramized = (ParameterizedTypeBinding) binding;
- if (paramized.arguments != null) {
- params = new TypeReference[paramized.arguments.length];
- for (int i = 0; i < params.length; i++) {
- params[i] = makeType(paramized.arguments[i], pos, true);
- }
+ boolean isParamized = false;
+
+ for (TypeReference[] tyParams : params) {
+ if (tyParams != null) {
+ isParamized = true;
+ break;
}
}
-
- if (params.length > 0) {
+ if (isParamized) {
if (parts.length > 1) {
- TypeReference[][] typeArguments = new TypeReference[parts.length][];
- typeArguments[typeArguments.length - 1] = params;
+ TypeReference[][] typeArguments = params.toArray(new TypeReference[0][]);
TypeReference result = new ParameterizedQualifiedTypeReference(parts, typeArguments, dims, poss(pos, parts.length));
setGeneratedBy(result, pos);
return result;
}
- TypeReference result = new ParameterizedSingleTypeReference(parts[0], params, dims, pos(pos));
+ TypeReference result = new ParameterizedSingleTypeReference(parts[0], params.get(0), dims, pos(pos));
setGeneratedBy(result, pos);
return result;
}
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java
index 29f261c6..da4b4762 100644
--- a/src/core/lombok/javac/JavacResolution.java
+++ b/src/core/lombok/javac/JavacResolution.java
@@ -362,18 +362,19 @@ public class JavacResolution {
return iterableParams.isEmpty() ? syms.objectType : types.upperBound(iterableParams.head);
}
- public static JCExpression typeToJCTree(Type type, TreeMaker maker, JavacAST ast, boolean allowVoid) throws TypeNotConvertibleException {
- return typeToJCTree(type, maker, ast, false, allowVoid);
+ public static JCExpression typeToJCTree(Type type, JavacAST ast, boolean allowVoid) throws TypeNotConvertibleException {
+ return typeToJCTree(type, ast, false, allowVoid);
}
- public static JCExpression createJavaLangObject(TreeMaker maker, JavacAST ast) {
+ public static JCExpression createJavaLangObject(JavacAST ast) {
+ TreeMaker maker = ast.getTreeMaker();
JCExpression out = maker.Ident(ast.toName("java"));
out = maker.Select(out, ast.toName("lang"));
out = maker.Select(out, ast.toName("Object"));
return out;
}
- private static JCExpression typeToJCTree(Type type, TreeMaker maker, JavacAST ast, boolean allowCompound, boolean allowVoid) throws TypeNotConvertibleException {
+ private static JCExpression typeToJCTree(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid) throws TypeNotConvertibleException {
int dims = 0;
Type type0 = type;
while (type0 instanceof ArrayType) {
@@ -381,20 +382,22 @@ public class JavacResolution {
type0 = ((ArrayType)type0).elemtype;
}
- JCExpression result = typeToJCTree0(type0, maker, ast, allowCompound, allowVoid);
+ JCExpression result = typeToJCTree0(type0, ast, allowCompound, allowVoid);
while (dims > 0) {
- result = maker.TypeArray(result);
+ result = ast.getTreeMaker().TypeArray(result);
dims--;
}
return result;
}
- private static JCExpression typeToJCTree0(Type type, TreeMaker maker, JavacAST ast, boolean allowCompound, boolean allowVoid) throws TypeNotConvertibleException {
+ private static JCExpression typeToJCTree0(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid) throws TypeNotConvertibleException {
// NB: There's such a thing as maker.Type(type), but this doesn't work very well; it screws up anonymous classes, captures, and adds an extra prefix dot for some reason too.
// -- so we write our own take on that here.
- if (type.tag == Javac.getCtcInt(TypeTags.class, "BOT")) return createJavaLangObject(maker, ast);
- if (type.tag == Javac.getCtcInt(TypeTags.class, "VOID")) return allowVoid ? primitiveToJCTree(type.getKind(), maker) : createJavaLangObject(maker, ast);
+ TreeMaker maker = ast.getTreeMaker();
+
+ if (type.tag == Javac.getCtcInt(TypeTags.class, "BOT")) return createJavaLangObject(ast);
+ if (type.tag == Javac.getCtcInt(TypeTags.class, "VOID")) return allowVoid ? primitiveToJCTree(type.getKind(), maker) : createJavaLangObject(ast);
if (type.isPrimitive()) return primitiveToJCTree(type.getKind(), maker);
if (type.isErroneous()) throw new TypeNotConvertibleException("Type cannot be resolved");
@@ -411,9 +414,9 @@ 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, allowVoid);
+ return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid);
}
- if (supertype != null) return typeToJCTree(supertype, maker, ast, allowCompound, allowVoid);
+ if (supertype != null) return typeToJCTree(supertype, ast, allowCompound, allowVoid);
}
throw new TypeNotConvertibleException("Anonymous inner class");
}
@@ -432,34 +435,52 @@ public class JavacResolution {
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(upper, maker, ast, false, false));
+ return maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), typeToJCTree(upper, ast, false, false));
} else {
- return maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), typeToJCTree(lower, maker, ast, false, false));
+ return maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), typeToJCTree(lower, ast, false, false));
}
}
if (upper != null) {
- return typeToJCTree(upper, maker, ast, allowCompound, allowVoid);
+ return typeToJCTree(upper, ast, allowCompound, allowVoid);
}
- return createJavaLangObject(maker, ast);
+ return createJavaLangObject(ast);
+ }
+
+ String qName;
+ if (symbol.isLocal()) {
+ qName = symbol.getSimpleName().toString();
+ } else if (symbol.type != null && symbol.type.getEnclosingType() != null && symbol.type.getEnclosingType().tag == TypeTags.CLASS) {
+ replacement = typeToJCTree0(type.getEnclosingType(), ast, false, false);
+ qName = symbol.getSimpleName().toString();
+ } else {
+ qName = symbol.getQualifiedName().toString();
}
- String qName = symbol.getQualifiedName().toString();
if (qName.isEmpty()) throw new TypeNotConvertibleException("unknown type");
if (qName.startsWith("<")) throw new TypeNotConvertibleException(qName);
- String[] baseNames = symbol.getQualifiedName().toString().split("\\.");
- replacement = maker.Ident(ast.toName(baseNames[0]));
- for (int i = 1; i < baseNames.length; i++) {
+ String[] baseNames = qName.split("\\.");
+ int i = 0;
+
+ if (replacement == null) {
+ replacement = maker.Ident(ast.toName(baseNames[0]));
+ i = 1;
+ }
+ for (; i < baseNames.length; i++) {
replacement = maker.Select(replacement, ast.toName(baseNames[i]));
}
+ return genericsToJCTreeNodes(generics, ast, replacement);
+ }
+
+ private static JCExpression genericsToJCTreeNodes(List<Type> generics, JavacAST ast, JCExpression rawTypeNode) throws TypeNotConvertibleException {
if (generics != null && !generics.isEmpty()) {
ListBuffer<JCExpression> args = ListBuffer.lb();
- for (Type t : generics) args.append(typeToJCTree(t, maker, ast, true, false));
- replacement = maker.TypeApply(replacement, args.toList());
+ for (Type t : generics) args.append(typeToJCTree(t, ast, true, false));
+ return ast.getTreeMaker().TypeApply(rawTypeNode, args.toList());
}
- return replacement;
+ return rawTypeNode;
}
private static JCExpression primitiveToJCTree(TypeKind kind, TreeMaker maker) throws TypeNotConvertibleException {
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index 3674ae5a..ac0d61d1 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -277,7 +277,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
}
JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annotations);
- JCExpression returnType = JavacResolution.typeToJCTree((Type) sig.type.getReturnType(), maker, annotation.getAst(), true);
+ JCExpression returnType = JavacResolution.typeToJCTree((Type) sig.type.getReturnType(), annotation.getAst(), true);
boolean useReturn = sig.type.getReturnType().getKind() != TypeKind.VOID;
ListBuffer<JCVariableDecl> params = sig.type.getParameterTypes().isEmpty() ? null : new ListBuffer<JCVariableDecl>();
ListBuffer<JCExpression> args = sig.type.getParameterTypes().isEmpty() ? null : new ListBuffer<JCExpression>();
@@ -293,7 +293,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
}
for (TypeMirror ex : sig.type.getThrownTypes()) {
- thrown.append(JavacResolution.typeToJCTree((Type) ex, maker, annotation.getAst(), true));
+ thrown.append(JavacResolution.typeToJCTree((Type) ex, annotation.getAst(), true));
}
int idx = 0;
@@ -301,7 +301,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
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));
+ params.append(maker.VarDef(paramMods, name, JavacResolution.typeToJCTree((Type) param, annotation.getAst(), true), null));
args.append(maker.Ident(name));
}
diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java
index cb5d33b9..2ddd8cc6 100644
--- a/src/core/lombok/javac/handlers/HandleVal.java
+++ b/src/core/lombok/javac/handlers/HandleVal.java
@@ -82,7 +82,7 @@ public class HandleVal extends JavacASTAdapter {
local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation);
}
- local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());
+ local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
Type type;
try {
@@ -107,24 +107,24 @@ public class HandleVal extends JavacASTAdapter {
if (rhsOfEnhancedForLoop != null) {
Type componentType = JavacResolution.ifTypeIsIterableToComponent(type, localNode.getAst());
- if (componentType == null) replacement = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());
- else replacement = JavacResolution.typeToJCTree(componentType, localNode.getTreeMaker(), localNode.getAst(), false);
+ if (componentType == null) replacement = JavacResolution.createJavaLangObject(localNode.getAst());
+ else replacement = JavacResolution.typeToJCTree(componentType, localNode.getAst(), false);
} else {
- replacement = JavacResolution.typeToJCTree(type, localNode.getTreeMaker(), localNode.getAst(), false);
+ replacement = JavacResolution.typeToJCTree(type, localNode.getAst(), false);
}
if (replacement != null) {
local.vartype = replacement;
} else {
- local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());
+ local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
}
localNode.getAst().setChanged();
} catch (JavacResolution.TypeNotConvertibleException e) {
localNode.addError("Cannot use 'val' here because initializer expression does not have a representable type: " + e.getMessage());
- local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());
+ local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
}
} catch (RuntimeException e) {
- local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());
+ local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
throw e;
} finally {
recursiveSetGeneratedBy(local.vartype, source);
diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java
index 0cf7e0c7..b2200bbd 100644
--- a/test/core/src/lombok/AbstractRunTests.java
+++ b/test/core/src/lombok/AbstractRunTests.java
@@ -103,8 +103,7 @@ public abstract class AbstractRunTests {
}
try {
compareContent(name, expectedMessages, actualMessages);
- }
- catch (Throwable e) {
+ } catch (Throwable e) {
if (printErrors) {
System.out.println("***** " + name + " *****");
System.out.println(e.getMessage());