diff options
-rw-r--r-- | src/core/lombok/javac/Javac.java | 14 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleVal.java | 114 |
2 files changed, 72 insertions, 56 deletions
diff --git a/src/core/lombok/javac/Javac.java b/src/core/lombok/javac/Javac.java index 6d9800ab..f4e3f141 100644 --- a/src/core/lombok/javac/Javac.java +++ b/src/core/lombok/javac/Javac.java @@ -36,6 +36,7 @@ import lombok.core.TypeResolver; import lombok.core.AST.Kind; import lombok.core.AnnotationValues.AnnotationValue; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCExpression; @@ -61,7 +62,18 @@ public class Javac { */ public static boolean annotationTypeMatches(Class<? extends Annotation> type, JavacNode node) { if (node.getKind() != Kind.ANNOTATION) return false; - String typeName = ((JCAnnotation)node.get()).annotationType.toString(); + return typeMatches(type, node, ((JCAnnotation)node.get()).annotationType); + } + + /** + * Checks if the given TypeReference node is likely to be a reference to the provided class. + * + * @param type An actual type. This method checks if {@code typeNode} is likely to be a reference to this type. + * @param node A Lombok AST node. Any node in the appropriate compilation unit will do (used to get access to import statements). + * @param typeNode A type reference to check. + */ + public static boolean typeMatches(Class<?> type, JavacNode node, JCTree typeNode) { + String typeName = typeNode.toString(); TypeLibrary library = new TypeLibrary(); library.addType(type.getName()); diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 98142a3b..14b0b44e 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -21,6 +21,8 @@ */ package lombok.javac.handlers; +import lombok.val; +import lombok.javac.Javac; import lombok.javac.JavacASTAdapter; import lombok.javac.JavacASTVisitor; import lombok.javac.JavacNode; @@ -43,71 +45,73 @@ public class HandleVal extends JavacASTAdapter { } @Override public void visitLocal(JavacNode localNode, JCVariableDecl local) { - if (local.vartype != null && local.vartype.toString().equals("val")) { - JCExpression rhsOfEnhancedForLoop = null; - if (local.init == null) { - JCTree parentRaw = localNode.directUp().get(); - if (parentRaw instanceof JCEnhancedForLoop) { - JCEnhancedForLoop efl = (JCEnhancedForLoop) parentRaw; - if (efl.var == local) rhsOfEnhancedForLoop = efl.expr; - } - } - - if (rhsOfEnhancedForLoop == null && local.init == null) { - localNode.addError("'val' on a local variable requires an initializer expression"); - return; + if (local.vartype == null || (!local.vartype.toString().equals("val") && !local.vartype.toString().equals("lombok.val"))) return; + + if (!Javac.typeMatches(val.class, localNode, local.vartype)) return; + + JCExpression rhsOfEnhancedForLoop = null; + if (local.init == null) { + JCTree parentRaw = localNode.directUp().get(); + if (parentRaw instanceof JCEnhancedForLoop) { + JCEnhancedForLoop efl = (JCEnhancedForLoop) parentRaw; + if (efl.var == local) rhsOfEnhancedForLoop = efl.expr; } - - if (local.init instanceof JCNewArray && ((JCNewArray)local.init).elemtype == null) { - localNode.addError("'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })"); - return; + } + + if (rhsOfEnhancedForLoop == null && local.init == null) { + localNode.addError("'val' on a local variable requires an initializer expression"); + return; + } + + if (local.init instanceof JCNewArray && ((JCNewArray)local.init).elemtype == null) { + localNode.addError("'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })"); + return; + } + + local.mods.flags |= Flags.FINAL; + local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst()); + + Type type; + try { + if (rhsOfEnhancedForLoop == null) { + if (local.init.type == null) { + JavacResolution resolver = new JavacResolution(localNode.getContext()); + type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type; + } else { + type = local.init.type; + } + } else { + if (rhsOfEnhancedForLoop.type == null) { + JavacResolution resolver = new JavacResolution(localNode.getContext()); + type = ((JCExpression) resolver.resolveMethodMember(localNode.directUp()).get(rhsOfEnhancedForLoop)).type; + } else { + type = rhsOfEnhancedForLoop.type; + } } - local.mods.flags |= Flags.FINAL; - local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst()); - - Type type; try { - if (rhsOfEnhancedForLoop == null) { - if (local.init.type == null) { - JavacResolution resolver = new JavacResolution(localNode.getContext()); - type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type; - } else { - type = local.init.type; - } + JCExpression replacement; + + 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); } else { - if (rhsOfEnhancedForLoop.type == null) { - JavacResolution resolver = new JavacResolution(localNode.getContext()); - type = ((JCExpression) resolver.resolveMethodMember(localNode.directUp()).get(rhsOfEnhancedForLoop)).type; - } else { - type = rhsOfEnhancedForLoop.type; - } + replacement = JavacResolution.typeToJCTree(type, localNode.getTreeMaker(), localNode.getAst(), false); } - try { - JCExpression replacement; - - 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); - } else { - replacement = JavacResolution.typeToJCTree(type, localNode.getTreeMaker(), localNode.getAst(), false); - } - - if (replacement != null) { - local.vartype = replacement; - localNode.getAst().setChanged(); - } - else local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());; - } 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());; + if (replacement != null) { + local.vartype = replacement; + localNode.getAst().setChanged(); } - } catch (RuntimeException e) { + else local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());; + } 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());; - throw e; } + } catch (RuntimeException e) { + local.vartype = JavacResolution.createJavaLangObject(localNode.getTreeMaker(), localNode.getAst());; + throw e; } } } |