aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorBulgakov Alexander <abulgakov@at-consulting.ru>2016-10-20 16:41:40 +0300
committerBulgakov Alexander <abulgakov@at-consulting.ru>2016-10-24 16:28:02 +0300
commit55619e8030768fb42f8a9b4207bb330806eaceef (patch)
tree1b46b9ed40a2b03aae727a3a5900ec6356a2a82d /src/core
parent4d9da60f4f2643302e53267ef150ee4c68c39d7c (diff)
downloadlombok-55619e8030768fb42f8a9b4207bb330806eaceef.tar.gz
lombok-55619e8030768fb42f8a9b4207bb330806eaceef.tar.bz2
lombok-55619e8030768fb42f8a9b4207bb330806eaceef.zip
added supporting of @var variables. The @var annotation has the same functionality as the @val except 'final' modifier.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lombok/ConfigurationKeys.java3
-rw-r--r--src/core/lombok/eclipse/handlers/HandleVal.java34
-rw-r--r--src/core/lombok/javac/handlers/HandleVal.java89
-rw-r--r--src/core/lombok/var.java28
4 files changed, 100 insertions, 54 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/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java
index d4ae417c..1f54bfac 100644
--- a/src/core/lombok/eclipse/handlers/HandleVal.java
+++ b/src/core/lombok/eclipse/handlers/HandleVal.java
@@ -22,6 +22,8 @@
package lombok.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.typeMatches;
+
import lombok.ConfigurationKeys;
import lombok.val;
import lombok.core.HandlerPriority;
@@ -30,10 +32,12 @@ import lombok.eclipse.EclipseASTAdapter;
import lombok.eclipse.EclipseASTVisitor;
import lombok.eclipse.EclipseNode;
+import lombok.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.TypeReference;
import org.mangosdk.spi.ProviderFor;
/*
@@ -44,33 +48,39 @@ 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;
-
+
if (localNode.directUp().get() instanceof ForeachStatement) {
ForeachStatement fs = (ForeachStatement) localNode.directUp().get();
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.");
}
}
}
diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java
index 337ab2d7..f4c816d6 100644
--- a/src/core/lombok/javac/handlers/HandleVal.java
+++ b/src/core/lombok/javac/handlers/HandleVal.java
@@ -21,50 +21,52 @@
*/
package lombok.javac.handlers;
-import static lombok.core.handlers.HandlerUtil.*;
-import static lombok.javac.handlers.JavacHandlerUtil.*;
-import lombok.ConfigurationKeys;
-import lombok.val;
-import lombok.core.HandlerPriority;
-import lombok.javac.JavacASTAdapter;
-import lombok.javac.JavacASTVisitor;
-import lombok.javac.JavacNode;
-import lombok.javac.JavacResolution;
-import lombok.javac.ResolutionResetNeeded;
-
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
-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.JCNewArray;
-import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.List;
+import lombok.ConfigurationKeys;
+import lombok.core.HandlerPriority;
+import lombok.javac.*;
+import lombok.val;
+import lombok.var;
+import org.mangosdk.spi.ProviderFor;
+
+import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
+import static lombok.javac.handlers.JavacHandlerUtil.recursiveSetGeneratedBy;
+import static lombok.javac.handlers.JavacHandlerUtil.typeMatches;
@ProviderFor(JavacASTVisitor.class)
@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,32 +74,37 @@ 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, "lombok.val");
+ JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, "lombok.var");
+ }
+
+ 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);
}
-
+
if (JavacResolution.platformHasTargetTyping()) {
local.vartype = localNode.getAst().getTreeMaker().Ident(localNode.getAst().toName("___Lombok_VAL_Attrib__"));
} else {
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
}
-
+
Type type;
try {
if (rhsOfEnhancedForLoop == null) {
@@ -130,10 +137,10 @@ public class HandleVal extends JavacASTAdapter {
type = rhsOfEnhancedForLoop.type;
}
}
-
+
try {
JCExpression replacement;
-
+
if (rhsOfEnhancedForLoop != null) {
Type componentType = JavacResolution.ifTypeIsIterableToComponent(type, localNode.getAst());
if (componentType == null) replacement = JavacResolution.createJavaLangObject(localNode.getAst());
@@ -141,7 +148,7 @@ public class HandleVal extends JavacASTAdapter {
} else {
replacement = JavacResolution.typeToJCTree(type, localNode.getAst(), false);
}
-
+
if (replacement != null) {
local.vartype = replacement;
} else {
diff --git a/src/core/lombok/var.java b/src/core/lombok/var.java
new file mode 100644
index 00000000..397f2760
--- /dev/null
+++ b/src/core/lombok/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;
+
+/**
+ * like val but not final
+ */
+public @interface var {
+}