diff options
author | Roel Spilker <r.spilker@gmail.com> | 2016-11-21 22:05:32 +0100 |
---|---|---|
committer | Roel Spilker <r.spilker@gmail.com> | 2016-11-21 22:05:32 +0100 |
commit | 369518c92ce4e79ce62ce334497c9309e074f44c (patch) | |
tree | 3cb84cf0975e2f66d030b027fa73505c9dd0e574 /src/core | |
parent | 192c569128d1ffb879fb104f44483e394032a790 (diff) | |
parent | bae2018180e9eaf31b8a71a1f7d06e2265452f5c (diff) | |
download | lombok-369518c92ce4e79ce62ce334497c9309e074f44c.tar.gz lombok-369518c92ce4e79ce62ce334497c9309e074f44c.tar.bz2 lombok-369518c92ce4e79ce62ce334497c9309e074f44c.zip |
Merge branch 'bulgakovalexander-feature/var'
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/lombok/ConfigurationKeys.java | 3 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/AllowHelper.java | 37 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/FlagUsageType.java | 2 | ||||
-rw-r--r-- | src/core/lombok/core/handlers/HandlerUtil.java | 10 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleVal.java | 32 | ||||
-rw-r--r-- | src/core/lombok/experimental/var.java | 28 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleVal.java | 60 |
7 files changed, 141 insertions, 31 deletions
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 04decf69..132bde8d 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -283,7 +283,8 @@ public class ConfigurationKeys { * If set, <em>any</em> usage of {@code val} results in a warning / error. */ public static final ConfigurationKey<FlagUsageType> VAL_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.val.flagUsage", "Emit a warning or error if 'val' is used.") {}; - + public static final ConfigurationKey<FlagUsageType> VAR_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.var.flagUsage", "Emit a warning or error if 'var' is used.") {}; + // ##### Extern ##### // ----- Logging ----- diff --git a/src/core/lombok/core/configuration/AllowHelper.java b/src/core/lombok/core/configuration/AllowHelper.java new file mode 100644 index 00000000..31d09381 --- /dev/null +++ b/src/core/lombok/core/configuration/AllowHelper.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.core.configuration; + +import java.util.HashSet; +import java.util.Set; + +import static java.util.Arrays.asList; + +public class AllowHelper { + private final static Set<String> allowable = new HashSet<String>(asList( + "var" + )); + + public static boolean isAllowable(String feature) { + return allowable.contains(feature); + } +} diff --git a/src/core/lombok/core/configuration/FlagUsageType.java b/src/core/lombok/core/configuration/FlagUsageType.java index b7053b7c..8717c22b 100644 --- a/src/core/lombok/core/configuration/FlagUsageType.java +++ b/src/core/lombok/core/configuration/FlagUsageType.java @@ -23,5 +23,5 @@ package lombok.core.configuration; /** Used for lombok configuration to flag usages of certain lombok feature. */ public enum FlagUsageType { - WARNING, ERROR; + WARNING, ERROR, ALLOW; } diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index a9a4be78..a321e67f 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -43,6 +43,7 @@ import lombok.core.AST; import lombok.core.AnnotationValues; import lombok.core.JavaIdentifiers; import lombok.core.LombokNode; +import lombok.core.configuration.AllowHelper; import lombok.core.configuration.ConfigurationKey; import lombok.core.configuration.FlagUsageType; import lombok.experimental.Accessors; @@ -95,12 +96,19 @@ public class HandlerUtil { return Singulars.autoSingularize(plural); } public static void handleFlagUsage(LombokNode<?, ?, ?> node, ConfigurationKey<FlagUsageType> key, String featureName) { + boolean allowable = AllowHelper.isAllowable(featureName); + FlagUsageType fut = node.getAst().readConfiguration(key); + boolean allowed = !allowable || FlagUsageType.ALLOW == fut; + if (!allowed) { + node.addError("Use of " + featureName + " is disabled by default. Please use flag " + FlagUsageType.ALLOW + " to enable."); + } + if (fut != null) { String msg = "Use of " + featureName + " is flagged according to lombok configuration."; if (fut == FlagUsageType.WARNING) node.addWarning(msg); - else node.addError(msg); + else if (fut == FlagUsageType.ERROR) node.addError(msg); } } diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java index d4ae417c..d8901067 100644 --- a/src/core/lombok/eclipse/handlers/HandleVal.java +++ b/src/core/lombok/eclipse/handlers/HandleVal.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 The Project Lombok Authors. + * Copyright (C) 2010-2016 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,7 +21,8 @@ */ package lombok.eclipse.handlers; -import static lombok.core.handlers.HandlerUtil.*; +import static lombok.core.handlers.HandlerUtil.handleFlagUsage; +import static lombok.eclipse.handlers.EclipseHandlerUtil.typeMatches; import lombok.ConfigurationKeys; import lombok.val; import lombok.core.HandlerPriority; @@ -29,11 +30,14 @@ import lombok.eclipse.DeferUntilPostDiet; import lombok.eclipse.EclipseASTAdapter; import lombok.eclipse.EclipseASTVisitor; import lombok.eclipse.EclipseNode; +import lombok.experimental.var; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ForStatement; import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; +import org.eclipse.jdt.internal.compiler.ast.NullLiteral; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.mangosdk.spi.ProviderFor; /* @@ -44,8 +48,13 @@ import org.mangosdk.spi.ProviderFor; @HandlerPriority(65536) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated. public class HandleVal extends EclipseASTAdapter { @Override public void visitLocal(EclipseNode localNode, LocalDeclaration local) { - if (!EclipseHandlerUtil.typeMatches(val.class, localNode, local.type)) return; - handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val"); + TypeReference type = local.type; + boolean isVal = typeMatches(val.class, localNode, type); + boolean isVar = typeMatches(var.class, localNode, type); + if (!(isVal || isVar)) return; + + if (isVal) handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val"); + if (isVar) handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var"); boolean variableOfForEach = false; @@ -54,23 +63,30 @@ public class HandleVal extends EclipseASTAdapter { variableOfForEach = fs.elementVariable == local; } + String annotation = isVal ? "val" : "var"; if (local.initialization == null && !variableOfForEach) { - localNode.addError("'val' on a local variable requires an initializer expression"); + localNode.addError("'" + annotation + "' on a local variable requires an initializer expression"); return; } if (local.initialization instanceof ArrayInitializer) { - localNode.addError("'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })"); + localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })"); return; } - if (localNode.directUp().get() instanceof ForStatement) { + if (isVal && localNode.directUp().get() instanceof ForStatement) { localNode.addError("'val' is not allowed in old-style for loops"); return; } if (local.initialization != null && local.initialization.getClass().getName().equals("org.eclipse.jdt.internal.compiler.ast.LambdaExpression")) { - localNode.addError("'val' is not allowed with lambda expressions."); + localNode.addError("'" + annotation + "' is not allowed with lambda expressions."); + return; + } + + if(isVar && local.initialization instanceof NullLiteral) { + localNode.addError("variable initializer is 'null'"); + return; } } } diff --git a/src/core/lombok/experimental/var.java b/src/core/lombok/experimental/var.java new file mode 100644 index 00000000..d8de8b19 --- /dev/null +++ b/src/core/lombok/experimental/var.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010-2013 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.experimental; + +/** + * like val but not final + */ +public @interface var { +} diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 337ab2d7..2976eabe 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2015 The Project Lombok Authors. + * Copyright (C) 2010-2016 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,11 +21,12 @@ */ package lombok.javac.handlers; -import static lombok.core.handlers.HandlerUtil.*; +import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.javac.handlers.JavacHandlerUtil.*; import lombok.ConfigurationKeys; import lombok.val; import lombok.core.HandlerPriority; +import lombok.experimental.var; import lombok.javac.JavacASTAdapter; import lombok.javac.JavacASTVisitor; import lombok.javac.JavacNode; @@ -42,6 +43,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCForLoop; +import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; @@ -50,21 +52,31 @@ import com.sun.tools.javac.util.List; @HandlerPriority(65536) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated. @ResolutionResetNeeded public class HandleVal extends JavacASTAdapter { - @Override public void visitLocal(JavacNode localNode, JCVariableDecl local) { + + private static boolean eq(String typeTreeToString, String key) { + return (typeTreeToString.equals(key) || typeTreeToString.equals("lombok." + key)); + } + + @Override + public void visitLocal(JavacNode localNode, JCVariableDecl local) { JCTree typeTree = local.vartype; if (typeTree == null) return; String typeTreeToString = typeTree.toString(); - if (!typeTreeToString.equals("val") && !typeTreeToString.equals("lombok.val")) return; - if (!typeMatches(val.class, localNode, typeTree)) return; - - handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val"); - + + if (!(eq(typeTreeToString, "val") || eq(typeTreeToString, "var"))) return; + boolean isVal = typeMatches(val.class, localNode, typeTree); + boolean isVar = typeMatches(var.class, localNode, typeTree); + if (!(isVal || isVar)) return; + + if (isVal) handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val"); + if (isVar) handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var"); + JCTree parentRaw = localNode.directUp().get(); - if (parentRaw instanceof JCForLoop) { + if (isVal && parentRaw instanceof JCForLoop) { localNode.addError("'val' is not allowed in old-style for loops"); return; } - + JCExpression rhsOfEnhancedForLoop = null; if (local.init == null) { if (parentRaw instanceof JCEnhancedForLoop) { @@ -72,21 +84,26 @@ public class HandleVal extends JavacASTAdapter { if (efl.var == local) rhsOfEnhancedForLoop = efl.expr; } } - + + final String annotation = typeTreeToString; if (rhsOfEnhancedForLoop == null && local.init == null) { - localNode.addError("'val' on a local variable requires an initializer expression"); + localNode.addError("'" + annotation + "' 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 { ... })"); + localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })"); return; } - - if (localNode.shouldDeleteLombokAnnotations()) JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, "lombok.val"); - - local.mods.flags |= Flags.FINAL; - + + if (localNode.shouldDeleteLombokAnnotations()) { + JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, val.class.getName()); + JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, var.class.getName()); + } + + if (isVal) local.mods.flags |= Flags.FINAL; + if (!localNode.shouldDeleteLombokAnnotations()) { JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeTree, localNode.getContext()); local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation); @@ -102,6 +119,9 @@ public class HandleVal extends JavacASTAdapter { try { if (rhsOfEnhancedForLoop == null) { if (local.init.type == null) { + if (isVar && local.init instanceof JCLiteral && ((JCLiteral) local.init).value == null) { + localNode.addError("variable initializer is 'null'"); + } JavacResolution resolver = new JavacResolution(localNode.getContext()); try { type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type; @@ -149,7 +169,7 @@ public class HandleVal extends JavacASTAdapter { } localNode.getAst().setChanged(); } catch (JavacResolution.TypeNotConvertibleException e) { - localNode.addError("Cannot use 'val' here because initializer expression does not have a representable type: " + e.getMessage()); + localNode.addError("Cannot use '" + annotation + "' here because initializer expression does not have a representable type: " + e.getMessage()); local.vartype = JavacResolution.createJavaLangObject(localNode.getAst()); } } catch (RuntimeException e) { |