added supporting of @var variables. The @var annotation has the same functionality as the @val except 'final' modifier.

This commit is contained in:
Bulgakov Alexander committed 2016-10-24 16:28:02 +03:00
1 parent 4d9da60f4f
commit 55619e8030
18 files changed
+321 -106

No files matched your search

+2 -1
View File
@@ -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 -----
+22 -12
View File
@@ -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.");
}
}
}
+48 -41
View File
@@ -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 {
+28
View File
@@ -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 {
}
@@ -21,11 +21,6 @@
*/
package lombok.eclipse.agent;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import java.lang.reflect.Field;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
@@ -43,14 +38,19 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import java.lang.reflect.Field;
import static lombok.eclipse.Eclipse.poss;
import static lombok.eclipse.handlers.EclipseHandlerUtil.makeType;
public class PatchVal {
// This is half of the work for 'val' support - the other half is in PatchValEclipse. This half is enough for ecj.
// Creates a copy of the 'initialization' field on a LocalDeclaration if the type of the LocalDeclaration is 'val', because the completion parser will null this out,
// which in turn stops us from inferring the intended type for 'val x = 5;'. We look at the copy.
// Also patches local declaration to not call .resolveType() on the initializer expression if we've already done so (calling it twice causes weird errors),
// and patches .resolve() on LocalDeclaration itself to just-in-time replace the 'val' vartype with the right one.
public static TypeBinding skipResolveInitializerIfAlreadyCalled(Expression expr, BlockScope scope) {
if (expr.resolvedType != null) return expr.resolvedType;
try {
@@ -62,7 +62,7 @@ public class PatchVal {
return null;
}
}
public static TypeBinding skipResolveInitializerIfAlreadyCalled2(Expression expr, BlockScope scope, LocalDeclaration decl) {
if (decl != null && LocalDeclaration.class.equals(decl.getClass()) && expr.resolvedType != null) return expr.resolvedType;
try {
@@ -74,56 +74,56 @@ public class PatchVal {
return null;
}
}
public static boolean matches(String key, char[] array) {
if (array == null || key.length() != array.length) return false;
for (int i = 0; i < array.length; i++) {
if (key.charAt(i) != array[i]) return false;
}
return true;
}
public static boolean couldBeVal(TypeReference ref) {
public static boolean couldBe(String key, TypeReference ref) {
if (ref instanceof SingleTypeReference) {
char[] token = ((SingleTypeReference)ref).token;
return matches("val", token);
return matches(key, token);
}
if (ref instanceof QualifiedTypeReference) {
char[][] tokens = ((QualifiedTypeReference)ref).tokens;
if (tokens == null || tokens.length != 2) return false;
return matches("lombok", tokens[0]) && matches("val", tokens[1]);
return matches("lombok", tokens[0]) && matches(key, tokens[1]);
}
return false;
}
private static boolean isVal(TypeReference ref, BlockScope scope) {
if (!couldBeVal(ref)) return false;
private static boolean is(TypeReference ref, BlockScope scope, String key) {
if (!couldBe(key, ref)) return false;
TypeBinding resolvedType = ref.resolvedType;
if (resolvedType == null) resolvedType = ref.resolveType(scope, false);
if (resolvedType == null) return false;
char[] pkg = resolvedType.qualifiedPackageName();
char[] nm = resolvedType.qualifiedSourceName();
return matches("lombok", pkg) && matches("val", nm);
return matches("lombok", pkg) && matches(key, nm);
}
public static final class Reflection {
private static final Field initCopyField, iterableCopyField;
static {
Field a = null, b = null;
try {
a = LocalDeclaration.class.getDeclaredField("$initCopy");
b = LocalDeclaration.class.getDeclaredField("$iterableCopy");
} catch (Throwable t) {
//ignore - no $initCopy exists when running in ecj.
}
initCopyField = a;
iterableCopyField = b;
}
@@ -131,18 +131,22 @@ public class PatchVal {
public static boolean handleValForLocalDeclaration(LocalDeclaration local, BlockScope scope) {
if (local == null || !LocalDeclaration.class.equals(local.getClass())) return false;
boolean decomponent = false;
if (!isVal(local.type, scope)) return false;
boolean val = is(local.type, scope, "val");
boolean var = is(local.type, scope, "var");
if (!(val || var)) return false;
StackTraceElement[] st = new Throwable().getStackTrace();
for (int i = 0; i < st.length - 2 && i < 10; i++) {
if (st[i].getClassName().equals("lombok.launch.PatchFixesHider$Val")) {
if (st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") &&
st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement")) return false;
boolean valInForStatement = val &&
st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") &&
st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement");
if (valInForStatement) return false;
break;
}
}
Expression init = local.initialization;
if (init == null && Reflection.initCopyField != null) {
try {
@@ -151,7 +155,7 @@ public class PatchVal {
// init remains null.
}
}
if (init == null && Reflection.iterableCopyField != null) {
try {
init = (Expression) Reflection.iterableCopyField.get(local);
@@ -186,8 +190,8 @@ public class PatchVal {
}
}
}
local.modifiers |= ClassFileConstants.AccFinal;
if(val) local.modifiers |= ClassFileConstants.AccFinal;
local.annotations = addValAnnotation(local.annotations, local.type, scope);
local.type = replacement != null ? replacement : new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(local.type, 3));
@@ -196,21 +200,23 @@ public class PatchVal {
public static boolean handleValForForEach(ForeachStatement forEach, BlockScope scope) {
if (forEach.elementVariable == null) return false;
if (!isVal(forEach.elementVariable.type, scope)) return false;
boolean val = is(forEach.elementVariable.type, scope, "val");
boolean var = is(forEach.elementVariable.type, scope, "var");
if (!(val || var)) return false;
TypeBinding component = getForEachComponentType(forEach.collection, scope);
if (component == null) return false;
TypeReference replacement = makeType(component, forEach.elementVariable.type, false);
forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
if (val) forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
forEach.elementVariable.annotations = addValAnnotation(forEach.elementVariable.annotations, forEach.elementVariable.type, scope);
forEach.elementVariable.type = replacement != null ? replacement :
new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3));
return false;
}
private static Annotation[] addValAnnotation(Annotation[] originals, TypeReference originalRef, BlockScope scope) {
Annotation[] newAnn;
if (originals != null) {
@@ -219,12 +225,12 @@ public class PatchVal {
} else {
newAnn = new Annotation[1];
}
newAnn[newAnn.length - 1] = new org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation(originalRef, originalRef.sourceStart);
return newAnn;
}
private static TypeBinding getForEachComponentType(Expression collection, BlockScope scope) {
if (collection != null) {
TypeBinding resolved = collection.resolvedType;
@@ -235,7 +241,7 @@ public class PatchVal {
return resolved;
} else if (resolved instanceof ReferenceBinding) {
ReferenceBinding iterableType = ((ReferenceBinding)resolved).findSuperTypeOriginatingFrom(TypeIds.T_JavaLangIterable, false);
TypeBinding[] arguments = null;
if (iterableType != null) switch (iterableType.kind()) {
case Binding.GENERIC_TYPE : // for (T t : Iterable<T>) - in case used inside Iterable itself
@@ -247,16 +253,16 @@ public class PatchVal {
case Binding.RAW_TYPE : // for(Object e : Iterable)
return null;
}
if (arguments != null && arguments.length == 1) {
return arguments[0];
}
}
}
return null;
}
private static TypeBinding resolveForExpression(Expression collection, BlockScope scope) {
try {
return collection.resolveType(scope);
@@ -65,7 +65,9 @@ public class PatchValEclipse {
ForeachStatement foreachDecl = (ForeachStatement) astStack[astPtr];
ASTNode init = foreachDecl.collection;
if (init == null) return;
if (foreachDecl.elementVariable == null || !PatchVal.couldBeVal(foreachDecl.elementVariable.type)) return;
boolean val = PatchVal.couldBe("val", foreachDecl.elementVariable.type);
boolean var = PatchVal.couldBe("var", foreachDecl.elementVariable.type);
if (foreachDecl.elementVariable == null || !(val || var)) return;
try {
if (Reflection.iterableCopyField != null) Reflection.iterableCopyField.set(foreachDecl.elementVariable, init);
@@ -88,7 +90,9 @@ public class PatchValEclipse {
if (!(variableDecl instanceof LocalDeclaration)) return;
ASTNode init = variableDecl.initialization;
if (init == null) return;
if (!PatchVal.couldBeVal(variableDecl.type)) return;
boolean val = PatchVal.couldBe("val", variableDecl.type);
boolean var = PatchVal.couldBe("var", variableDecl.type);
if (!(val || var)) return;
try {
if (Reflection.initCopyField != null) Reflection.initCopyField.set(variableDecl, init);
@@ -115,7 +119,7 @@ public class PatchValEclipse {
Annotation valAnnotation = null;
for (Annotation ann : in.annotations) {
if (PatchVal.couldBeVal(ann.type)) {
if (PatchVal.couldBe("val", ann.type)) {
found = true;
valAnnotation = ann;
break;
@@ -0,0 +1,20 @@
public class VarComplex {
private String field = "";
private static final int CONSTANT = 20;
public void testComplex() {
char[] shouldBeCharArray = field.toCharArray();
int shouldBeInt = CONSTANT;
java.lang.Object lock = new Object();
synchronized (lock) {
int field = 20; //Shadowing
int inner = 10;
switch (field) {
case 5:
char[] shouldBeCharArray2 = shouldBeCharArray;
int innerInner = inner;
}
}
java.lang.String shouldBeString = field; //Unshadowing
}
}
@@ -0,0 +1,9 @@
public class VarInFor {
public void enhancedFor() {
int[] list = new int[] {1, 2};
for (int shouldBeInt : list) {
System.out.println(shouldBeInt);
int shouldBeInt2 = shouldBeInt;
}
}
}
@@ -0,0 +1,7 @@
public class VarInForOld {
public void oldFor() {
for (int i = 0; i < 100; ++i) {
System.out.println(i);
}
}
}
@@ -0,0 +1,7 @@
public class VarModifier {
private String field = "";
public void testComplex() {
final char[] shouldBeFinalCharArray = field.toCharArray();
char[] shouldBeCharArray = field.toCharArray();
}
}
@@ -0,0 +1,26 @@
import lombok.var;
public class VarComplex {
private String field = "";
private static final int CONSTANT = 20;
<clinit>() {
}
public VarComplex() {
super();
}
public void testComplex() {
@var char[] shouldBeCharArray = field.toCharArray();
@var int shouldBeInt = CONSTANT;
@var java.lang.Object lock = new Object();
synchronized (lock)
{
@var int field = 20;
@var int inner = 10;
switch (field) {
case 5 :
@var char[] shouldBeCharArray2 = shouldBeCharArray;
@var int innerInner = inner;
}
}
@var java.lang.String shouldBeString = field;
}
}
@@ -0,0 +1,14 @@
import lombok.var;
public class VarInFor {
public VarInFor() {
super();
}
public void enhancedFor() {
int[] list = new int[]{1, 2};
for (@var int shouldBeInt : list)
{
System.out.println(shouldBeInt);
@var int shouldBeInt2 = shouldBeInt;
}
}
}
@@ -0,0 +1,12 @@
import lombok.var;
public class VarInForOld {
public VarInForOld() {
super();
}
public void oldFor() {
for (@var int i = 0;; (i < 100); ++ i)
{
System.out.println(i);
}
}
}
@@ -0,0 +1,12 @@
import lombok.var;
public class VarModifier {
private String field = "";
public VarModifier() {
super();
}
public void testComplex() {
final @var char[] shouldBeFinalCharArray = field.toCharArray();
@var char[] shouldBeCharArray = field.toCharArray();
}
}
@@ -0,0 +1,22 @@
import lombok.var;
public class VarComplex {
private String field = "";
private static final int CONSTANT = 20;
public void testComplex() {
var shouldBeCharArray = field.toCharArray();
var shouldBeInt = CONSTANT;
var lock = new Object();
synchronized (lock) {
var field = 20; //Shadowing
var inner = 10;
switch (field) {
case 5:
var shouldBeCharArray2 = shouldBeCharArray;
var innerInner = inner;
}
}
var shouldBeString = field; //Unshadowing
}
}
@@ -0,0 +1,11 @@
import lombok.var;
public class VarInFor {
public void enhancedFor() {
int[] list = new int[] {1, 2};
for (var shouldBeInt : list) {
System.out.println(shouldBeInt);
var shouldBeInt2 = shouldBeInt;
}
}
}
@@ -0,0 +1,9 @@
import lombok.var;
public class VarInForOld {
public void oldFor() {
for (var i = 0; i < 100; ++i) {
System.out.println(i);
}
}
}
@@ -0,0 +1,10 @@
import lombok.var;
public class VarModifier {
private String field = "";
public void testComplex() {
final var shouldBeFinalCharArray = field.toCharArray();
var shouldBeCharArray = field.toCharArray();
}
}