From 60f575496b3184c2279e9dba470097ed164d5adf Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Sat, 29 May 2021 18:49:05 +0200 Subject: [fixes #2838] Handle anonymous classes properly Generated qualified names (e.g. Outer.Inner) now stop at anonymous classes instead of adding an empty part. All handlers that add static fields/methods/types now add error messages instead of generating invalid code. --- .../eclipse/handlers/EclipseHandlerUtil.java | 24 +++++++++++++++++++++- .../lombok/eclipse/handlers/HandleBuilder.java | 5 +++++ .../eclipse/handlers/HandleEqualsAndHashCode.java | 9 ++++---- .../eclipse/handlers/HandleFieldNameConstants.java | 14 ++++++------- src/core/lombok/eclipse/handlers/HandleLog.java | 5 +++++ .../eclipse/handlers/HandleSuperBuilder.java | 4 ++++ .../lombok/eclipse/handlers/HandleToString.java | 4 +++- 7 files changed, 51 insertions(+), 14 deletions(-) (limited to 'src/core/lombok/eclipse') diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 5eea980c..a9f435fd 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1042,7 +1042,7 @@ public class EclipseHandlerUtil { res[count] = name; n = parent; - while (n != null && n.getKind() == Kind.TYPE && n.get() instanceof TypeDeclaration) { + while (count > 0) { TypeDeclaration td = (TypeDeclaration) n.get(); res[--count] = td.name; n = n.up(); @@ -2635,6 +2635,13 @@ public class EclipseHandlerUtil { return isTypeAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | AccRecord); } + /** + * Returns {@code true} if the provided node is an actual class, an enum or a record and not some other type declaration (so, not an annotation definition or interface). + */ + public static boolean isClassEnumOrRecord(EclipseNode typeNode) { + return isTypeAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation); + } + /** * Returns {@code true} if the provided node is a record declaration (so, not an annotation definition, interface, enum, or plain class). */ @@ -2662,6 +2669,21 @@ public class EclipseHandlerUtil { return (modifiers & flags) == 0; } + /** + * Returns {@code true} if the provided node supports static methods and types (top level or static class) + */ + public static boolean isStaticAllowed(EclipseNode typeNode) { + boolean staticAllowed = true; + + while (typeNode.getKind() != Kind.COMPILATION_UNIT) { + if (!staticAllowed) return false; + + staticAllowed = typeNode.isStatic(); + typeNode = typeNode.up(); + } + return true; + } + public static AbstractVariableDeclaration[] getRecordComponents(TypeDeclaration typeDeclaration) { if (typeDeclaration == null || (typeDeclaration.modifiers & AccRecord) == 0) return null; try { diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index dab774f3..82d3bfcf 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -293,6 +293,11 @@ public class HandleBuilder extends EclipseAnnotationHandler { List nonFinalNonDefaultedFields = null; + if (!isStaticAllowed(upToTypeNode(parent))) { + annotationNode.addError("@Builder is not supported on non-static nested classes."); + return; + } + if (parent.get() instanceof TypeDeclaration) { if (!isClass(parent) && !isRecord(parent)) { annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR); diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 12a3c315..a5e8dfb5 100755 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -538,14 +538,15 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler { annotationNode.addError("@SuperBuilder is only supported on classes."); return; } + if (!isStaticAllowed(parent)) { + annotationNode.addError("@SuperBuilder is not supported on non-static nested classes."); + return; + } job.parentType = parent; TypeDeclaration td = (TypeDeclaration) parent.get(); diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java index 171402b3..05b0e069 100644 --- a/src/core/lombok/eclipse/handlers/HandleToString.java +++ b/src/core/lombok/eclipse/handlers/HandleToString.java @@ -315,7 +315,9 @@ public class HandleToString extends EclipseAnnotationHandler { String typeName = getSingleTypeName(type); EclipseNode upType = type.up(); while (upType.getKind() == Kind.TYPE) { - typeName = getSingleTypeName(upType) + "." + typeName; + String upTypeName = getSingleTypeName(upType); + if (upTypeName.isEmpty()) break; + typeName = upTypeName + "." + typeName; upType = upType.up(); } return typeName; -- cgit From fdcbaa033d27b344adfea99d8d7bdd99cceacfb3 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Tue, 2 Feb 2021 09:44:36 +0100 Subject: Replace val with native final var in Java >= 10 --- src/core/lombok/eclipse/handlers/HandleVal.java | 20 ++++++++++++++++++-- src/core/lombok/javac/JavacAST.java | 2 +- src/core/lombok/javac/handlers/HandleVal.java | 6 ++++++ src/eclipseAgent/lombok/eclipse/agent/PatchVal.java | 12 ++++++++++++ src/utils/lombok/eclipse/Eclipse.java | 7 +++++-- .../javac/java8/CommentCollectingScannerFactory.java | 3 ++- .../resource/after-delombok/ValSwitchExpression.java | 4 ++-- .../resource/after-delombok/ValToNative.java | 15 +++++++++++++++ .../resource/after-ecj/ValSwitchExpression.java | 4 ++-- test/transform/resource/after-ecj/ValToNative.java | 19 +++++++++++++++++++ test/transform/resource/before/MixGetterVal.java | 1 + .../resource/before/TrickyTypeResolution.java | 1 + .../before/ValAnonymousSubclassWithGenerics.java | 1 + test/transform/resource/before/ValComplex.java | 1 + test/transform/resource/before/ValDefault.java | 2 +- .../resource/before/ValDelegateMethodReference.java | 2 +- test/transform/resource/before/ValErrors.java | 1 + test/transform/resource/before/ValFinal.java | 1 + test/transform/resource/before/ValInBasicFor.java | 1 + test/transform/resource/before/ValInFor.java | 1 + test/transform/resource/before/ValInLambda.java | 2 +- .../resource/before/ValInMultiDeclaration.java | 1 + .../resource/before/ValInTryWithResources.java | 2 +- test/transform/resource/before/ValLambda.java | 2 +- test/transform/resource/before/ValLessSimple.java | 1 + test/transform/resource/before/ValLub.java | 1 + test/transform/resource/before/ValNullInit.java | 1 + .../resource/before/ValOutersWithGenerics.java | 1 + test/transform/resource/before/ValRawType.java | 1 + test/transform/resource/before/ValSimple.java | 1 + test/transform/resource/before/ValToNative.java | 19 +++++++++++++++++++ test/transform/resource/before/ValWeirdTypes.java | 2 +- test/transform/resource/before/ValWithLabel.java | 1 + .../resource/before/ValWithLocalClasses.java | 1 + .../resource/before/ValWithSelfRefGenerics.java | 1 + website/templates/features/val.html | 3 +++ 36 files changed, 128 insertions(+), 16 deletions(-) create mode 100644 test/transform/resource/after-delombok/ValToNative.java create mode 100644 test/transform/resource/after-ecj/ValToNative.java create mode 100644 test/transform/resource/before/ValToNative.java (limited to 'src/core/lombok/eclipse') diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java index ac53e27e..0f70e66d 100644 --- a/src/core/lombok/eclipse/handlers/HandleVal.java +++ b/src/core/lombok/eclipse/handlers/HandleVal.java @@ -22,12 +22,14 @@ package lombok.eclipse.handlers; import static lombok.core.handlers.HandlerUtil.handleFlagUsage; -import static lombok.eclipse.handlers.EclipseHandlerUtil.typeMatches; +import static lombok.eclipse.handlers.EclipseHandlerUtil.*; + import lombok.ConfigurationKeys; import lombok.val; import lombok.var; import lombok.core.HandlerPriority; import lombok.eclipse.DeferUntilPostDiet; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseASTAdapter; import lombok.eclipse.EclipseASTVisitor; import lombok.eclipse.EclipseNode; @@ -39,10 +41,13 @@ 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.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; /* - * This class just handles 3 basic error cases. The real meat of eclipse 'val' support is in {@code PatchVal} and {@code PatchValEclipse}. + * Java 1-9: This class just handles 3 basic error cases. The real meat of eclipse 'val' support is in {@code PatchVal} and {@code PatchValEclipse}. + * Java 10+: Lombok uses the native 'var' support and transforms 'val' to 'final var'. */ @Provides(EclipseASTVisitor.class) @DeferUntilPostDiet @@ -96,5 +101,16 @@ public class HandleVal extends EclipseASTAdapter { localNode.addError("variable initializer is 'null'"); return; } + + // For Java >= 10 we use native support + if (localNode.getSourceVersion() >= 10) { + if (isVal) { + TypeReference originalType = local.type; + local.type = new SingleTypeReference("var".toCharArray(), Eclipse.pos(local.type)); + local.modifiers |= ClassFileConstants.AccFinal; + local.annotations = addAnnotation(local.type, local.annotations, originalType.getTypeName()); + } + return; + } } } diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index f58de60f..0919c7d4 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -228,7 +228,7 @@ public class JavacAST extends AST { int underscoreIdx = nm.indexOf('_'); if (underscoreIdx > -1) return Integer.parseInt(nm.substring(underscoreIdx + 1)); // assume java9+ - return Integer.parseInt(nm); + return Integer.parseInt(nm.substring(3)); } catch (Exception ignore) {} return 6; } diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 0ed831ab..d4fb1027 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -115,6 +115,12 @@ public class HandleVal extends JavacASTAdapter { local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation); } + if (localNode.getSourceVersion() >= 10) { + local.vartype = null; + localNode.getAst().setChanged(); + return; + } + if (JavacResolution.platformHasTargetTyping()) { local.vartype = localNode.getAst().getTreeMaker().Ident(localNode.getAst().toName("___Lombok_VAL_Attrib__")); } else { diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java index 774e5b40..824ecefc 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java @@ -204,6 +204,8 @@ public class PatchVal { boolean var = isVar(local, scope); if (!(val || var)) return false; + if (hasNativeVarSupport(scope)) return false; + if (val) { StackTraceElement[] st = new Throwable().getStackTrace(); for (int i = 0; i < st.length - 2 && i < 10; i++) { @@ -281,6 +283,14 @@ public class PatchVal { return is(local.type, scope, "lombok.val"); } + private static boolean hasNativeVarSupport(Scope scope) { + long sl = scope.problemReporter().options.sourceLevel >> 16; + long cl = scope.problemReporter().options.complianceLevel >> 16; + if (sl == 0) sl = cl; + if (cl == 0) cl = sl; + return Math.min((int)(sl - 44), (int)(cl - 44)) >= 10; + } + public static boolean handleValForForEach(ForeachStatement forEach, BlockScope scope) { if (forEach.elementVariable == null) return false; @@ -288,6 +298,8 @@ public class PatchVal { boolean var = isVar(forEach.elementVariable, scope); if (!(val || var)) return false; + if (hasNativeVarSupport(scope)) return false; + TypeBinding component = getForEachComponentType(forEach.collection, scope); if (component == null) return false; TypeReference replacement = makeType(component, forEach.elementVariable.type, false); diff --git a/src/utils/lombok/eclipse/Eclipse.java b/src/utils/lombok/eclipse/Eclipse.java index 8af481b9..0f42ddc6 100644 --- a/src/utils/lombok/eclipse/Eclipse.java +++ b/src/utils/lombok/eclipse/Eclipse.java @@ -224,8 +224,11 @@ public class Eclipse { int highestVersionSoFar = 0; for (Field f : ClassFileConstants.class.getDeclaredFields()) { try { - if (f.getName().startsWith("JDK1_")) { - int thisVersion = Integer.parseInt(f.getName().substring("JDK1_".length())); + if (f.getName().startsWith("JDK")) { + String versionString = f.getName().substring("JDK".length()); + if (versionString.startsWith("1_")) versionString = versionString.substring("1_".length()); + + int thisVersion = Integer.parseInt(versionString); if (thisVersion > highestVersionSoFar) { highestVersionSoFar = thisVersion; latestEcjCompilerVersionConstantCached = (Long) f.get(null); diff --git a/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java b/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java index f29f501b..e625cd8d 100644 --- a/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java +++ b/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java @@ -21,6 +21,7 @@ */ package lombok.javac.java8; +import java.nio.Buffer; import java.nio.CharBuffer; import com.sun.tools.javac.parser.Scanner; @@ -79,7 +80,7 @@ public class CommentCollectingScannerFactory extends ScannerFactory { int limit; if (input instanceof CharBuffer && ((CharBuffer) input).hasArray()) { CharBuffer cb = (CharBuffer) input; - cb.compact().flip(); + ((Buffer)cb.compact()).flip(); array = cb.array(); limit = cb.limit(); } else { diff --git a/test/transform/resource/after-delombok/ValSwitchExpression.java b/test/transform/resource/after-delombok/ValSwitchExpression.java index a8fa9b0f..ba26c137 100644 --- a/test/transform/resource/after-delombok/ValSwitchExpression.java +++ b/test/transform/resource/after-delombok/ValSwitchExpression.java @@ -1,9 +1,9 @@ // version 14: public class ValSwitchExpression { public void method(int arg) { - final int x = switch (arg) { + final var x = switch (arg) { default -> { - final java.lang.String s = "string"; + final var s = "string"; yield arg; } }; diff --git a/test/transform/resource/after-delombok/ValToNative.java b/test/transform/resource/after-delombok/ValToNative.java new file mode 100644 index 00000000..64aff9e5 --- /dev/null +++ b/test/transform/resource/after-delombok/ValToNative.java @@ -0,0 +1,15 @@ +// version 10: +import java.io.IOException; +import java.util.Arrays; + +public class ValToNative { + private void test() throws IOException { + final var intField = 1; + for (final var s : Arrays.asList("1")) { + final var s2 = s; + } + try (var in = getClass().getResourceAsStream("ValToNative.class")) { + final var j = in.read(); + } + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValSwitchExpression.java b/test/transform/resource/after-ecj/ValSwitchExpression.java index 59b503cb..4e848572 100644 --- a/test/transform/resource/after-ecj/ValSwitchExpression.java +++ b/test/transform/resource/after-ecj/ValSwitchExpression.java @@ -5,10 +5,10 @@ public class ValSwitchExpression { super(); } public void method(int arg) { - final @val int x = switch (arg) { + final @val var x = switch (arg) { default -> { - final @val java.lang.String s = "string"; + final @val var s = "string"; yield arg; } }; diff --git a/test/transform/resource/after-ecj/ValToNative.java b/test/transform/resource/after-ecj/ValToNative.java new file mode 100644 index 00000000..2c8d721c --- /dev/null +++ b/test/transform/resource/after-ecj/ValToNative.java @@ -0,0 +1,19 @@ +import java.io.IOException; +import java.util.Arrays; +import lombok.val; +public class ValToNative { + public ValToNative() { + super(); + } + private void test() throws IOException { + final @val var intField = 1; + for (final @val var s : Arrays.asList("1")) + { + final @val var s2 = s; + } + try (final @val var in = getClass().getResourceAsStream("ValToNative.class")) + { + final @val var j = in.read(); + } + } +} \ No newline at end of file diff --git a/test/transform/resource/before/MixGetterVal.java b/test/transform/resource/before/MixGetterVal.java index 3f06b1a8..4568902b 100644 --- a/test/transform/resource/before/MixGetterVal.java +++ b/test/transform/resource/before/MixGetterVal.java @@ -1,3 +1,4 @@ +// version :9 import lombok.Getter; import lombok.val; diff --git a/test/transform/resource/before/TrickyTypeResolution.java b/test/transform/resource/before/TrickyTypeResolution.java index 94d97fe0..7f3866ee 100644 --- a/test/transform/resource/before/TrickyTypeResolution.java +++ b/test/transform/resource/before/TrickyTypeResolution.java @@ -1,3 +1,4 @@ +// version :9 import lombok.*; class TrickyDoNothing { @interface Getter {} diff --git a/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java index c0f8157a..a434ba9d 100644 --- a/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java +++ b/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java @@ -1,3 +1,4 @@ +// version :9 // issue 205: val inside anonymous inner classes is a bit tricky in javac, this test ensures we don't break it. import java.util.*; import lombok.val; diff --git a/test/transform/resource/before/ValComplex.java b/test/transform/resource/before/ValComplex.java index e20124a2..f1898cfd 100644 --- a/test/transform/resource/before/ValComplex.java +++ b/test/transform/resource/before/ValComplex.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValComplex { diff --git a/test/transform/resource/before/ValDefault.java b/test/transform/resource/before/ValDefault.java index 75124c3c..ded4b074 100644 --- a/test/transform/resource/before/ValDefault.java +++ b/test/transform/resource/before/ValDefault.java @@ -1,4 +1,4 @@ -// version 8: +// version 8:9 interface ValDefault { int size(); diff --git a/test/transform/resource/before/ValDelegateMethodReference.java b/test/transform/resource/before/ValDelegateMethodReference.java index 3d1f082c..8cfc2c33 100644 --- a/test/transform/resource/before/ValDelegateMethodReference.java +++ b/test/transform/resource/before/ValDelegateMethodReference.java @@ -1,4 +1,4 @@ -//version 8: +//version 8:9 //platform !eclipse: Requires a 'full' eclipse with intialized workspace, and we don't (yet) have that set up properly in the test run. import lombok.Getter; import lombok.Setter; diff --git a/test/transform/resource/before/ValErrors.java b/test/transform/resource/before/ValErrors.java index 87383719..290a1f72 100644 --- a/test/transform/resource/before/ValErrors.java +++ b/test/transform/resource/before/ValErrors.java @@ -1,3 +1,4 @@ +// version :9 // unchanged import lombok.val; diff --git a/test/transform/resource/before/ValFinal.java b/test/transform/resource/before/ValFinal.java index 3c5af366..293c9bce 100644 --- a/test/transform/resource/before/ValFinal.java +++ b/test/transform/resource/before/ValFinal.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValFinal { public void test() { diff --git a/test/transform/resource/before/ValInBasicFor.java b/test/transform/resource/before/ValInBasicFor.java index a109bcd3..b137f0d7 100644 --- a/test/transform/resource/before/ValInBasicFor.java +++ b/test/transform/resource/before/ValInBasicFor.java @@ -1,3 +1,4 @@ +// version :9 // unchanged import lombok.val; diff --git a/test/transform/resource/before/ValInFor.java b/test/transform/resource/before/ValInFor.java index 35332b34..f2c50139 100644 --- a/test/transform/resource/before/ValInFor.java +++ b/test/transform/resource/before/ValInFor.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValInFor { diff --git a/test/transform/resource/before/ValInLambda.java b/test/transform/resource/before/ValInLambda.java index 6750d045..a13c79d2 100644 --- a/test/transform/resource/before/ValInLambda.java +++ b/test/transform/resource/before/ValInLambda.java @@ -1,4 +1,4 @@ -// version 8: +// version 8:9 import java.util.function.Function; import java.util.function.Supplier; diff --git a/test/transform/resource/before/ValInMultiDeclaration.java b/test/transform/resource/before/ValInMultiDeclaration.java index 1c333ebb..0f4e604b 100644 --- a/test/transform/resource/before/ValInMultiDeclaration.java +++ b/test/transform/resource/before/ValInMultiDeclaration.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValInMultiDeclaration { public void test() { diff --git a/test/transform/resource/before/ValInTryWithResources.java b/test/transform/resource/before/ValInTryWithResources.java index a7820062..5c885f79 100644 --- a/test/transform/resource/before/ValInTryWithResources.java +++ b/test/transform/resource/before/ValInTryWithResources.java @@ -1,4 +1,4 @@ -//version 7: +//version 7:9 import lombok.val; import java.io.IOException; diff --git a/test/transform/resource/before/ValLambda.java b/test/transform/resource/before/ValLambda.java index e956bcd3..8f55d222 100644 --- a/test/transform/resource/before/ValLambda.java +++ b/test/transform/resource/before/ValLambda.java @@ -1,4 +1,4 @@ -// version 8: +// version 8:9 import java.io.Serializable; class ValLambda { diff --git a/test/transform/resource/before/ValLessSimple.java b/test/transform/resource/before/ValLessSimple.java index b81cc22c..1ed738cc 100644 --- a/test/transform/resource/before/ValLessSimple.java +++ b/test/transform/resource/before/ValLessSimple.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValLessSimple { diff --git a/test/transform/resource/before/ValLub.java b/test/transform/resource/before/ValLub.java index 509a4f8b..e3b55950 100644 --- a/test/transform/resource/before/ValLub.java +++ b/test/transform/resource/before/ValLub.java @@ -1,3 +1,4 @@ +// version :9 class ValLub { public void easyLub() { java.util.Map m = java.util.Collections.emptyMap(); diff --git a/test/transform/resource/before/ValNullInit.java b/test/transform/resource/before/ValNullInit.java index 649bc0cd..c1610af3 100644 --- a/test/transform/resource/before/ValNullInit.java +++ b/test/transform/resource/before/ValNullInit.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; class ValNullInit { diff --git a/test/transform/resource/before/ValOutersWithGenerics.java b/test/transform/resource/before/ValOutersWithGenerics.java index 1b29d37c..99b71735 100644 --- a/test/transform/resource/before/ValOutersWithGenerics.java +++ b/test/transform/resource/before/ValOutersWithGenerics.java @@ -1,3 +1,4 @@ +// version :9 import java.util.*; import lombok.val; diff --git a/test/transform/resource/before/ValRawType.java b/test/transform/resource/before/ValRawType.java index 3ef8527e..fa47c536 100644 --- a/test/transform/resource/before/ValRawType.java +++ b/test/transform/resource/before/ValRawType.java @@ -1,3 +1,4 @@ +// version :9 import java.util.List; import lombok.val; diff --git a/test/transform/resource/before/ValSimple.java b/test/transform/resource/before/ValSimple.java index 04763be2..5d1911da 100644 --- a/test/transform/resource/before/ValSimple.java +++ b/test/transform/resource/before/ValSimple.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValSimple { diff --git a/test/transform/resource/before/ValToNative.java b/test/transform/resource/before/ValToNative.java new file mode 100644 index 00000000..3b4e6fa8 --- /dev/null +++ b/test/transform/resource/before/ValToNative.java @@ -0,0 +1,19 @@ +// version 10: +import java.io.IOException; +import java.util.Arrays; + +import lombok.val; + +public class ValToNative { + private void test() throws IOException { + val intField = 1; + + for (val s : Arrays.asList("1")) { + val s2 = s; + } + + try (val in = getClass().getResourceAsStream("ValToNative.class")) { + val j = in.read(); + } + } +} diff --git a/test/transform/resource/before/ValWeirdTypes.java b/test/transform/resource/before/ValWeirdTypes.java index f62feca6..710e236b 100644 --- a/test/transform/resource/before/ValWeirdTypes.java +++ b/test/transform/resource/before/ValWeirdTypes.java @@ -1,4 +1,4 @@ -// version 8: In java6/7, lub types worked differently, so, the `arraysAsList` method has a slightly different inferred type there. +// version 8:9 In java6/7, lub types worked differently, so, the `arraysAsList` method has a slightly different inferred type there. import java.math.BigDecimal; import java.util.*; import lombok.val; diff --git a/test/transform/resource/before/ValWithLabel.java b/test/transform/resource/before/ValWithLabel.java index f7c3402a..9e15f937 100644 --- a/test/transform/resource/before/ValWithLabel.java +++ b/test/transform/resource/before/ValWithLabel.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValWithLabel { diff --git a/test/transform/resource/before/ValWithLocalClasses.java b/test/transform/resource/before/ValWithLocalClasses.java index 572a1e7d..0d145aa9 100644 --- a/test/transform/resource/before/ValWithLocalClasses.java +++ b/test/transform/resource/before/ValWithLocalClasses.java @@ -1,3 +1,4 @@ +// version :9 //issue 694: In javac, resolving the RHS (which is what val does) can cause an entire class to be resolved, breaking all usage of val inside that class. This tests that we handle that better. class ValWithLocalClasses1 { { diff --git a/test/transform/resource/before/ValWithSelfRefGenerics.java b/test/transform/resource/before/ValWithSelfRefGenerics.java index d0532606..fdb30d32 100644 --- a/test/transform/resource/before/ValWithSelfRefGenerics.java +++ b/test/transform/resource/before/ValWithSelfRefGenerics.java @@ -1,3 +1,4 @@ +// version :9 import lombok.val; public class ValWithSelfRefGenerics { public void run(Thing> thing, Thing thing2, java.util.List z) { diff --git a/website/templates/features/val.html b/website/templates/features/val.html index 32a8ffdf..1b137c65 100644 --- a/website/templates/features/val.html +++ b/website/templates/features/val.html @@ -5,6 +5,9 @@

val was introduced in lombok 0.10.

+

+ NEW in Lombok 1.18.22: val gets replaced with final var. +

<@f.overview>

-- cgit From c67acc023425bee9c1d0960e38bea94c2254a99a Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Mon, 27 Sep 2021 17:46:20 +0200 Subject: [fixes #2972] Use simple type, move code to patch method --- .../lombok/eclipse/handlers/EclipseHandlerUtil.java | 6 +----- src/core/lombok/eclipse/handlers/HandleVal.java | 19 ++----------------- src/eclipseAgent/lombok/eclipse/agent/PatchVal.java | 13 +++++++++---- 3 files changed, 12 insertions(+), 26 deletions(-) (limited to 'src/core/lombok/eclipse') diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index a9f435fd..b00b8ec1 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -2052,11 +2052,7 @@ public class EclipseHandlerUtil { } int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long)pS << 32 | pE; - long[] poss = new long[annotationTypeFqn.length]; - Arrays.fill(poss, p); - QualifiedTypeReference qualifiedType = new QualifiedTypeReference(annotationTypeFqn, poss); - setGeneratedBy(qualifiedType, source); + TypeReference qualifiedType = generateQualifiedTypeRef(source, annotationTypeFqn); Annotation ann; if (args != null && args.length == 1 && args[0] instanceof Expression) { SingleMemberAnnotation sma = new SingleMemberAnnotation(qualifiedType, pS); diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java index 0f70e66d..1bea5525 100644 --- a/src/core/lombok/eclipse/handlers/HandleVal.java +++ b/src/core/lombok/eclipse/handlers/HandleVal.java @@ -22,14 +22,13 @@ package lombok.eclipse.handlers; import static lombok.core.handlers.HandlerUtil.handleFlagUsage; -import static lombok.eclipse.handlers.EclipseHandlerUtil.*; +import static lombok.eclipse.handlers.EclipseHandlerUtil.typeMatches; import lombok.ConfigurationKeys; import lombok.val; import lombok.var; import lombok.core.HandlerPriority; import lombok.eclipse.DeferUntilPostDiet; -import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseASTAdapter; import lombok.eclipse.EclipseASTVisitor; import lombok.eclipse.EclipseNode; @@ -41,13 +40,10 @@ 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.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; /* - * Java 1-9: This class just handles 3 basic error cases. The real meat of eclipse 'val' support is in {@code PatchVal} and {@code PatchValEclipse}. - * Java 10+: Lombok uses the native 'var' support and transforms 'val' to 'final var'. + * This class just handles 3 basic error cases. The real meat of eclipse 'val' support is in {@code PatchVal} and {@code PatchValEclipse} */ @Provides(EclipseASTVisitor.class) @DeferUntilPostDiet @@ -101,16 +97,5 @@ public class HandleVal extends EclipseASTAdapter { localNode.addError("variable initializer is 'null'"); return; } - - // For Java >= 10 we use native support - if (localNode.getSourceVersion() >= 10) { - if (isVal) { - TypeReference originalType = local.type; - local.type = new SingleTypeReference("var".toCharArray(), Eclipse.pos(local.type)); - local.modifiers |= ClassFileConstants.AccFinal; - local.annotations = addAnnotation(local.type, local.annotations, originalType.getTypeName()); - } - return; - } } } diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java index 824ecefc..3e96e75d 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java @@ -59,8 +59,8 @@ import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import java.lang.reflect.Field; import static lombok.Lombok.sneakyThrow; -import static lombok.eclipse.Eclipse.poss; -import static lombok.eclipse.handlers.EclipseHandlerUtil.makeType; +import static lombok.eclipse.Eclipse.*; +import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import static org.eclipse.jdt.core.compiler.CategorizedProblem.CAT_TYPE; public class PatchVal { @@ -204,8 +204,6 @@ public class PatchVal { boolean var = isVar(local, scope); if (!(val || var)) return false; - if (hasNativeVarSupport(scope)) return false; - if (val) { StackTraceElement[] st = new Throwable().getStackTrace(); for (int i = 0; i < st.length - 2 && i < 10; i++) { @@ -239,6 +237,13 @@ public class PatchVal { TypeReference replacement = null; + // Java 10+: Lombok uses the native 'var' support and transforms 'val' to 'final var'. + if (hasNativeVarSupport(scope) && val) { + replacement = new SingleTypeReference("var".toCharArray(), pos(local.type)); + local.initialization = init; + init = null; + } + if (init != null) { if (init.getClass().getName().equals("org.eclipse.jdt.internal.compiler.ast.LambdaExpression")) { return false; -- cgit From 07cf64ed66416a4eaa5f6bf8216f307c62dbb0dc Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Thu, 23 Sep 2021 18:09:07 +0200 Subject: Support javadoc copying in ecj language server --- src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 14 +++++++++++++- .../lombok/eclipse/agent/EclipsePatcher.java | 8 ++++++++ src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java | 16 ++++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) (limited to 'src/core/lombok/eclipse') diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index b00b8ec1..f8cde6c8 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -95,6 +95,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; @@ -337,6 +338,8 @@ public class EclipseHandlerUtil { public static final Class INTERSECTION_BINDING1, INTERSECTION_BINDING2; public static final Field INTERSECTION_BINDING_TYPES1, INTERSECTION_BINDING_TYPES2; public static final Field TYPE_DECLARATION_RECORD_COMPONENTS; + public static final Class COMPILATION_UNIT; + public static final Method COMPILATION_UNIT_ORIGINAL_FROM_CLONE; static { STRING_LITERAL__LINE_NUMBER = getField(StringLiteral.class, "lineNumber"); ANNOTATION__MEMBER_VALUE_PAIR_NAME = getField(Annotation.class, "memberValuePairName"); @@ -346,6 +349,8 @@ public class EclipseHandlerUtil { INTERSECTION_BINDING_TYPES1 = INTERSECTION_BINDING1 == null ? null : getField(INTERSECTION_BINDING1, "intersectingTypes"); INTERSECTION_BINDING_TYPES2 = INTERSECTION_BINDING2 == null ? null : getField(INTERSECTION_BINDING2, "intersectingTypes"); TYPE_DECLARATION_RECORD_COMPONENTS = getField(TypeDeclaration.class, "recordComponents"); + COMPILATION_UNIT = getClass("org.eclipse.jdt.internal.core.CompilationUnit"); + COMPILATION_UNIT_ORIGINAL_FROM_CLONE = COMPILATION_UNIT == null ? null : Permit.permissiveGetMethod(COMPILATION_UNIT, "originalFromClone"); } public static int reflectInt(Field f, Object o) { @@ -2731,7 +2736,14 @@ public class EclipseHandlerUtil { public static void setDocComment(CompilationUnitDeclaration cud, TypeDeclaration type, ASTNode node, String doc) { if (doc == null) return; - Map docs = EcjAugments.CompilationUnit_javadoc.setIfAbsent(cud.compilationResult.compilationUnit, new HashMap()); + ICompilationUnit compilationUnit = cud.compilationResult.compilationUnit; + if (compilationUnit.getClass().equals(COMPILATION_UNIT)) { + try { + compilationUnit = (ICompilationUnit) Permit.invoke(COMPILATION_UNIT_ORIGINAL_FROM_CLONE, compilationUnit); + } catch (Throwable t) { } + } + + Map docs = EcjAugments.CompilationUnit_javadoc.setIfAbsent(compilationUnit, new HashMap()); if (node instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node; String signature = getSignature(type, methodDeclaration); diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java index 05d77b37..fe1c8608 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java @@ -892,6 +892,14 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable { .requestExtra(StackRequest.PARAM1) .build()); + /* This is a copy for the language server implementation that also supports markdown */ + sm.addScript(ScriptBuilder.wrapMethodCall() + .target(new MethodTarget("org.eclipse.jdt.ls.core.internal.javadoc.JavadocContentAccess2", "getHTMLContent", "java.lang.String", "org.eclipse.jdt.core.IJavaElement", "boolean")) + .methodToWrap(new Hook("org.eclipse.jdt.ls.core.internal.javadoc.JavadocContentAccess2", "getHTMLContentFromSource", "java.lang.String", "org.eclipse.jdt.core.IJavaElement")) + .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Javadoc", "getHTMLContentFromSource", "java.lang.String", "java.lang.String", "org.eclipse.jdt.core.IJavaElement")) + .requestExtra(StackRequest.PARAM1) + .build()); + /* This is an older version that uses IMember instead of IJavaElement */ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall() .target(new MethodTarget("org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2", "getHTMLContent", "java.lang.String", "org.eclipse.jdt.core.IMember", "boolean")) diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java index 5b34917e..673c30fd 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Project Lombok Authors. + * Copyright (C) 2020-2021 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 @@ -103,8 +103,9 @@ public class PatchJavadoc { private static class Reflection { private static final Method javadoc2HTML; private static final Method oldJavadoc2HTML; + private static final Method lsJavadoc2HTML; static { - Method a = null, b = null; + Method a = null, b = null, c = null; try { a = Permit.getMethod(JavadocContentAccess2.class, "javadoc2HTML", IMember.class, IJavaElement.class, String.class); @@ -112,9 +113,13 @@ public class PatchJavadoc { try { b = Permit.getMethod(JavadocContentAccess2.class, "javadoc2HTML", IMember.class, String.class); } catch (Throwable t) {} + try { + c = Permit.getMethod(Class.forName("org.eclipse.jdt.ls.core.internal.javadoc.JavadocContentAccess2"), "javadoc2HTML", IMember.class, IJavaElement.class, String.class); + } catch (Throwable t) {} javadoc2HTML = a; oldJavadoc2HTML = b; + lsJavadoc2HTML = c; } private static String javadoc2HTML(IMember member, IJavaElement element, String rawJavadoc) { @@ -125,6 +130,13 @@ public class PatchJavadoc { return null; } } + if (lsJavadoc2HTML != null) { + try { + return (String) lsJavadoc2HTML.invoke(null, member, element, rawJavadoc); + } catch (Throwable t) { + return null; + } + } if (oldJavadoc2HTML != null) { try { return (String) oldJavadoc2HTML.invoke(null, member, rawJavadoc); -- cgit From dbc67c5c2d0388692f9c9dec02b294da14fd5b56 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 18 Oct 2021 15:44:45 +0200 Subject: [#2693] Review and updates for javabeans-style capitalization lombok.config --- src/core/lombok/ConfigurationKeys.java | 10 +- src/core/lombok/core/AST.java | 18 +++- .../core/configuration/CapitalizationStrategy.java | 52 ++++++++++ .../lombok/core/configuration/FlagUsageType.java | 4 +- src/core/lombok/core/handlers/HandlerUtil.java | 58 ++++++----- .../lombok/eclipse/handlers/HandleBuilder.java | 6 +- .../eclipse/handlers/HandleSuperBuilder.java | 4 +- .../singulars/EclipseGuavaSingularizer.java | 10 +- .../EclipseJavaUtilListSetSingularizer.java | 10 +- .../singulars/EclipseJavaUtilMapSingularizer.java | 6 +- src/core/lombok/experimental/Accessors.java | 9 -- src/core/lombok/javac/handlers/HandleBuilder.java | 4 +- .../lombok/javac/handlers/HandleSuperBuilder.java | 4 +- .../javac/handlers/JavacSingularsRecipes.java | 6 +- .../BuilderWithJavaBeansSpecCapitalization.java | 106 +++++++++++++++++++++ .../GetterWithJavaBeansSpecCapitalization.java | 18 +--- .../SetterWithJavaBeansSpecCapitalization.java | 15 --- .../ValueWithJavaBeansSpecCapitalization.java | 11 --- .../WithOnJavaBeansSpecCapitalization.java | 29 ------ .../WithWithJavaBeansSpecCapitalization.java | 12 +++ .../BuilderWithJavaBeansSpecCapitalization.java | 99 +++++++++++++++++++ .../GetterWithJavaBeansSpecCapitalization.java | 24 +---- .../SetterWithJavaBeansSpecCapitalization.java | 24 +---- .../ValueWithJavaBeansSpecCapitalization.java | 31 +----- .../WithOnJavaBeansSpecCapitalization.java | 25 ----- .../WithWithJavaBeansSpecCapitalization.java | 12 +++ .../BuilderWithJavaBeansSpecCapitalization.java | 7 ++ .../GetterWithJavaBeansSpecCapitalization.java | 8 +- .../SetterWithJavaBeansSpecCapitalization.java | 8 +- .../ValueWithJavaBeansSpecCapitalization.java | 7 +- .../before/WithOnJavaBeansSpecCapitalization.java | 16 ---- .../WithWithJavaBeansSpecCapitalization.java | 8 ++ 32 files changed, 382 insertions(+), 279 deletions(-) create mode 100644 src/core/lombok/core/configuration/CapitalizationStrategy.java create mode 100644 test/transform/resource/after-delombok/BuilderWithJavaBeansSpecCapitalization.java delete mode 100644 test/transform/resource/after-delombok/WithOnJavaBeansSpecCapitalization.java create mode 100644 test/transform/resource/after-delombok/WithWithJavaBeansSpecCapitalization.java create mode 100644 test/transform/resource/after-ecj/BuilderWithJavaBeansSpecCapitalization.java delete mode 100644 test/transform/resource/after-ecj/WithOnJavaBeansSpecCapitalization.java create mode 100644 test/transform/resource/after-ecj/WithWithJavaBeansSpecCapitalization.java create mode 100644 test/transform/resource/before/BuilderWithJavaBeansSpecCapitalization.java delete mode 100644 test/transform/resource/before/WithOnJavaBeansSpecCapitalization.java create mode 100644 test/transform/resource/before/WithWithJavaBeansSpecCapitalization.java (limited to 'src/core/lombok/eclipse') diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 12307471..05550a06 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2020 The Project Lombok Authors. + * Copyright (C) 2013-2021 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 @@ -24,6 +24,7 @@ package lombok; import java.util.List; import lombok.core.configuration.CallSuperType; +import lombok.core.configuration.CapitalizationStrategy; import lombok.core.configuration.CheckerFrameworkVersion; import lombok.core.configuration.ConfigurationKey; import lombok.core.configuration.FlagUsageType; @@ -559,11 +560,12 @@ public class ConfigurationKeys { public static final ConfigurationKey ACCESSORS_FLUENT = new ConfigurationKey("lombok.accessors.fluent", "Generate getters and setters using only the field name (no get/set prefix) (default: false).") {}; /** - * lombok configuration: {@code lombok.accessors.javaBeansSpecCapitalization} = {@code true} | {@code false}. + * lombok configuration: {@code lombok.accessors.capitalization} = {@code basic} | {@code beanspec}. * - * For any class without an {@code @Accessors} that explicitly defines the {@code javaBeansSpecCapitalization} option, this value is used (default = false). + * Which capitalization rule is used to turn field names into getter/setter/with names and vice versa for field names that start with 1 lowercase letter, then 1 uppercase letter. + * basic = {@code uShape} becomes {@code getUShape}, beanspec = {@code uShape} becomes {@code getuShape} (default = basic). */ - public static final ConfigurationKey ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION = new ConfigurationKey("lombok.accessors.javaBeansSpecCapitalization", "Generating accessors name according to the JavaBeans Spec (default: false).") {}; + public static final ConfigurationKey ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION = new ConfigurationKey("lombok.accessors.capitalization", "Which capitalization strategy to use when converting field names to accessor names and vice versa (default: basic).") {}; // ----- ExtensionMethod ----- diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java index 9f3a471f..07d035c5 100755 --- a/src/core/lombok/core/AST.java +++ b/src/core/lombok/core/AST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2019 The Project Lombok Authors. + * Copyright (C) 2009-2021 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 @@ -430,6 +430,9 @@ public abstract class AST, L extends LombokNode, } } + /** + * @return The {@code lombok.config} configuration value for the provided {@code key}, or {@code null} if that key is not in the config / there is no config. + */ public final T readConfiguration(ConfigurationKey key) { long start = configTracker == null ? 0L : configTracker.start(); try { @@ -438,4 +441,17 @@ public abstract class AST, L extends LombokNode, if (configTracker != null) configTracker.end(start); } } + + /** + * @return The {@code lombok.config} configuration value for the provided {@code key}, or {@code defaultValue} if that key is not in the config / there is no config. + */ + public final T readConfigurationOr(ConfigurationKey key, T defaultValue) { + long start = configTracker == null ? 0L : configTracker.start(); + try { + T value = LombokConfiguration.read(key, this); + return value != null ? value : defaultValue; + } finally { + if (configTracker != null) configTracker.end(start); + } + } } diff --git a/src/core/lombok/core/configuration/CapitalizationStrategy.java b/src/core/lombok/core/configuration/CapitalizationStrategy.java new file mode 100644 index 00000000..affd3576 --- /dev/null +++ b/src/core/lombok/core/configuration/CapitalizationStrategy.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 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; + +/** Used for lombok configuration to determine how to transform field names when turning them into accessor method names and vice versa. */ +public enum CapitalizationStrategy { + BASIC { + @Override public String capitalize(String in) { + if (in.length() == 0) return in; + char first = in.charAt(0); + if (!Character.isLowerCase(first)) return in; + boolean useUpperCase = in.length() > 2 && + (Character.isTitleCase(in.charAt(1)) || Character.isUpperCase(in.charAt(1))); + return (useUpperCase ? Character.toUpperCase(first) : Character.toTitleCase(first)) + in.substring(1); + } + }, + BEANSPEC { + @Override public String capitalize(String in) { + if (in.length() == 0) return in; + char first = in.charAt(0); + if (!Character.isLowerCase(first) || (in.length() > 1 && Character.isUpperCase(in.charAt(1)))) return in; + boolean useUpperCase = in.length() > 2 && Character.isTitleCase(in.charAt(1)); + return (useUpperCase ? Character.toUpperCase(first) : Character.toTitleCase(first)) + in.substring(1); + } + }, + ; + + public static CapitalizationStrategy defaultValue() { + return BASIC; + } + + public abstract String capitalize(String in); +} diff --git a/src/core/lombok/core/configuration/FlagUsageType.java b/src/core/lombok/core/configuration/FlagUsageType.java index 8717c22b..293a2f1d 100644 --- a/src/core/lombok/core/configuration/FlagUsageType.java +++ b/src/core/lombok/core/configuration/FlagUsageType.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2021 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,7 @@ */ package lombok.core.configuration; -/** Used for lombok configuration to flag usages of certain lombok feature. */ +/** Used for lombok configuration to flag usages of certain lombok features. */ public enum FlagUsageType { WARNING, ERROR, ALLOW; } diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index f45481d4..c00b5dca 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2020 The Project Lombok Authors. + * Copyright (C) 2013-2021 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 @@ -46,6 +46,7 @@ import lombok.core.AnnotationValues; import lombok.core.JavaIdentifiers; import lombok.core.LombokNode; import lombok.core.configuration.AllowHelper; +import lombok.core.configuration.CapitalizationStrategy; import lombok.core.configuration.ConfigurationKey; import lombok.core.configuration.FlagUsageType; import lombok.experimental.Accessors; @@ -591,7 +592,7 @@ public class HandlerUtil { List prefix = explicitPrefix ? Arrays.asList(ac.prefix()) : ast.readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX); boolean fluent = explicitFluent ? ac.fluent() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT)); - boolean javaBeansSpecCapitalization = explicitJavaBeansSpecCapitalization ? ac.javaBeansSpecCapitalization() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION)); + CapitalizationStrategy capitalizationStrategy = ast.readConfigurationOr(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION, CapitalizationStrategy.defaultValue()); fieldName = removePrefix(fieldName, prefix); if (fieldName == null) return null; @@ -604,7 +605,7 @@ public class HandlerUtil { return booleanPrefix + fName.substring(2); } - return buildAccessorName(isBoolean ? booleanPrefix : normalPrefix, fName, javaBeansSpecCapitalization); + return buildAccessorName(isBoolean ? booleanPrefix : normalPrefix, fName, capitalizationStrategy); } /** @@ -677,14 +678,13 @@ public class HandlerUtil { boolean explicitPrefix = accessors != null && accessors.isExplicit("prefix"); boolean explicitFluent = accessors != null && accessors.isExplicit("fluent"); - boolean explicitJavaBeansSpecCapitalization = accessors != null && accessors.isExplicit("javaBeansSpecCapitalization"); - Accessors ac = (explicitPrefix || explicitFluent || explicitJavaBeansSpecCapitalization) ? accessors.getInstance() : null; + Accessors ac = (explicitPrefix || explicitFluent) ? accessors.getInstance() : null; List prefix = explicitPrefix ? Arrays.asList(ac.prefix()) : ast.readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX); boolean fluent = explicitFluent ? ac.fluent() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT)); - boolean javaBeansSpecCapitalization = explicitJavaBeansSpecCapitalization ? ac.javaBeansSpecCapitalization() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION)); - + CapitalizationStrategy capitalizationStrategy = ast.readConfigurationOr(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION, CapitalizationStrategy.defaultValue()); + fieldName = removePrefix(fieldName, prefix); if (fieldName == null) return Collections.emptyList(); @@ -695,8 +695,8 @@ public class HandlerUtil { if (adhereToFluent && fluent) { names.add(baseName); } else { - names.add(buildAccessorName(normalPrefix, baseName, javaBeansSpecCapitalization)); - if (!normalPrefix.equals(booleanPrefix)) names.add(buildAccessorName(booleanPrefix, baseName, javaBeansSpecCapitalization)); + names.add(buildAccessorName(normalPrefix, baseName, capitalizationStrategy)); + if (!normalPrefix.equals(booleanPrefix)) names.add(buildAccessorName(booleanPrefix, baseName, capitalizationStrategy)); } } @@ -722,40 +722,36 @@ public class HandlerUtil { } /** + * @param node Any node (used to fetch config of capitalization strategy). + * @param prefix Something like {@code get} or {@code set} or {@code is}. + * @param suffix Something like {@code running}. + * @return prefix + smartly title-cased suffix. For example, {@code setRunning}. + */ + public static String buildAccessorName(AST ast, String prefix, String suffix) { + CapitalizationStrategy capitalizationStrategy = ast.readConfigurationOr(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION, CapitalizationStrategy.defaultValue()); + return buildAccessorName(prefix, suffix, capitalizationStrategy); + } + + /** + * @param node Any node (used to fetch config of capitalization strategy). * @param prefix Something like {@code get} or {@code set} or {@code is}. * @param suffix Something like {@code running}. * @return prefix + smartly title-cased suffix. For example, {@code setRunning}. */ - public static String buildAccessorName(String prefix, String suffix) { - return buildAccessorName(prefix, suffix, false); + public static String buildAccessorName(LombokNode node, String prefix, String suffix) { + CapitalizationStrategy capitalizationStrategy = node.getAst().readConfigurationOr(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION, CapitalizationStrategy.defaultValue()); + return buildAccessorName(prefix, suffix, capitalizationStrategy); } /** * @param prefix Something like {@code get} or {@code set} or {@code is}. * @param suffix Something like {@code running}. - * @param shouldFollowJavaBeansSpecCapitalization {@code boolean} that indicates whether the capitalization rules should follow JavaBeanSpec - * @return if shouldFollowJavaBeansSpecCapitalization is {@code true} and name start with only single lowercase letter, returns simple suffix+prefix. For example, {@code setaFieldName} - * otherwise, returns prefix + smartly title-cased suffix. For example, {@code setRunning}. + * @param capitalizationStrategy Which strategy to use to capitalize the name part. */ - private static String buildAccessorName(String prefix, String suffix, boolean shouldFollowJavaBeansSpecCapitalization) { + private static String buildAccessorName(String prefix, String suffix, CapitalizationStrategy capitalizationStrategy) { if (suffix.length() == 0) return prefix; if (prefix.length() == 0) return suffix; - - char first = suffix.charAt(0); - if (!Character.isLowerCase(first)) { - return String.format("%s%s", prefix, suffix); - } - - boolean useUpperCase = suffix.length() > 2 && - (Character.isTitleCase(suffix.charAt(1)) || Character.isUpperCase(suffix.charAt(1))); - if (shouldFollowJavaBeansSpecCapitalization && useUpperCase) { - return String.format("%s%s", prefix, suffix); - } - - suffix = String.format("%s%s", - useUpperCase ? Character.toUpperCase(first) : Character.toTitleCase(first), - suffix.subSequence(1, suffix.length())); - return String.format("%s%s", prefix, suffix); + return prefix + capitalizationStrategy.capitalize(suffix); } public static String camelCaseToConstant(String fieldName) { diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 82d3bfcf..2bfe1e8b 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -665,7 +665,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { for (BuilderFieldData bfd : job.builderFields) { String setterName = new String(bfd.name); String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set"; - if (!setterPrefix.isEmpty()) setterName = HandlerUtil.buildAccessorName(setterPrefix, setterName); + if (!setterPrefix.isEmpty()) setterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, setterName); MessageSend ms = new MessageSend(); Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2]; @@ -1033,9 +1033,9 @@ public class HandleBuilder extends EclipseAnnotationHandler { String setterPrefix = prefix.isEmpty() ? "set" : prefix; String setterName; if (job.oldFluent) { - setterName = prefix.isEmpty() ? new String(bfd.name) : HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name)); + setterName = prefix.isEmpty() ? new String(bfd.name) : HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, new String(bfd.name)); } else { - setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name)); + setterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, new String(bfd.name)); } for (int i = 0; i < len; i++) { diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 5bc6c125..26b62cbf 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -798,7 +798,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { } private MessageSend createSetterCallWithInstanceValue(BuilderFieldData bfd, EclipseNode type, ASTNode source, String setterPrefix) { - char[] setterName = HandlerUtil.buildAccessorName(setterPrefix, String.valueOf(bfd.name)).toCharArray(); + char[] setterName = HandlerUtil.buildAccessorName(type, setterPrefix, String.valueOf(bfd.name)).toCharArray(); MessageSend ms = new MessageSend(); Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2]; @@ -1004,7 +1004,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { if (existing == null) existing = EMPTY_METHODS; int len = existing.length; - String setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(paramName)); + String setterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, new String(paramName)); for (int i = 0; i < len; i++) { if (!(existing[i] instanceof MethodDeclaration)) continue; diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index 7dcf18c9..9b464a25 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -126,7 +126,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = new ThisReference(0, 0); Assignment a = new Assignment(thisDotField, new NullLiteral(0, 0), 0); - md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray(); + md.selector = HandlerUtil.buildAccessorName(builderType, "clear", new String(data.getPluralName())).toCharArray(); md.statements = returnStatement != null ? new Statement[] {a, returnStatement} : new Statement[] {a}; md.returnType = returnType; md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); @@ -173,8 +173,8 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { md.arguments[i].annotations = typeUseAnns; } md.returnType = returnType; - char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray(); - md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray(); + char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray(); + md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName(builderType, "add", new String(data.getSingularName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up())); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); @@ -213,8 +213,8 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { md.arguments = new Argument[] {param}; md.returnType = returnType; - char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); - md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray(); + char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); + md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName(builderType, "addAll", new String(data.getPluralName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index 882b7adc..6f5e9add 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -112,7 +112,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula thisDotField.receiver = new ThisReference(0, 0); FieldReference thisDotField2 = new FieldReference(data.getPluralName(), 0L); thisDotField2.receiver = new ThisReference(0, 0); - md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray(); + md.selector = HandlerUtil.buildAccessorName(builderType, "clear", new String(data.getPluralName())).toCharArray(); MessageSend clearMsg = new MessageSend(); clearMsg.receiver = thisDotField2; clearMsg.selector = "clear".toCharArray(); @@ -151,8 +151,8 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula param.annotations = typeUseAnns; md.arguments = new Argument[] {param}; md.returnType = returnType; - char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray(); - md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray(); + char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray(); + md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName(builderType, "add", new String(data.getSingularName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up())); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); @@ -189,8 +189,8 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula md.arguments = new Argument[] {param}; md.returnType = returnType; - char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); - md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray(); + char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); + md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName(builderType, "addAll", new String(data.getPluralName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index a766612f..c28ba59d 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -177,7 +177,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer thisDotField2.receiver = new ThisReference(0, 0); FieldReference thisDotField3 = new FieldReference(valueFieldName, 0L); thisDotField3.receiver = new ThisReference(0, 0); - md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray(); + md.selector = HandlerUtil.buildAccessorName(builderType, "clear", new String(data.getPluralName())).toCharArray(); MessageSend clearMsg1 = new MessageSend(); clearMsg1.receiver = thisDotField2; clearMsg1.selector = "clear".toCharArray(); @@ -249,7 +249,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer String name = new String(data.getSingularName()); String setterPrefix = data.getSetterPrefix().length > 0 ? new String(data.getSetterPrefix()) : fluent ? "" : "put"; - String setterName = HandlerUtil.buildAccessorName(setterPrefix, name); + String setterName = HandlerUtil.buildAccessorName(builderType, setterPrefix, name); md.selector = setterName.toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); @@ -325,7 +325,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer String name = new String(data.getPluralName()); String setterPrefix = data.getSetterPrefix().length > 0 ? new String(data.getSetterPrefix()) : fluent ? "" : "put"; - String setterName = HandlerUtil.buildAccessorName(setterPrefix, name); + String setterName = HandlerUtil.buildAccessorName(builderType, setterPrefix, name); md.selector = setterName.toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); diff --git a/src/core/lombok/experimental/Accessors.java b/src/core/lombok/experimental/Accessors.java index b3da9a5b..dc9ae4b0 100644 --- a/src/core/lombok/experimental/Accessors.java +++ b/src/core/lombok/experimental/Accessors.java @@ -54,15 +54,6 @@ public @interface Accessors { */ boolean chain() default false; - /** - * If true, accessors names will be capitalized according to JavaBeans capitalization rules. - * If {@code true}, an accessor for a field that starts with a single lowercase letter followed by a capital letter, - * wont capitalize the first letter (named {@code getaFieldName()}, not for example {@code getAFieldName}). - * default: false - * @return - */ - boolean javaBeansSpecCapitalization() default false; - /** * If present, only fields with any of the stated prefixes are given the getter/setter treatment. * Note that a prefix only counts if the next character is NOT a lowercase character or the last diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index bb852b55..d8fdfb1b 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -636,7 +636,7 @@ public class HandleBuilder extends JavacAnnotationHandler { for (BuilderFieldData bfd : job.builderFields) { String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set"; String prefixedSetterName = bfd.name.toString(); - if (!setterPrefix.isEmpty()) prefixedSetterName = HandlerUtil.buildAccessorName(setterPrefix, prefixedSetterName); + if (!setterPrefix.isEmpty()) prefixedSetterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, prefixedSetterName); Name setterName = job.toName(prefixedSetterName); JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2]; @@ -901,7 +901,7 @@ public class HandleBuilder extends JavacAnnotationHandler { private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData bfd, boolean deprecate, String prefix) { JavacNode fieldNode = bfd.createdFields.get(0); String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set"; - String setterName = HandlerUtil.buildAccessorName(setterPrefix, bfd.name.toString()); + String setterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, bfd.name.toString()); Name setterName_ = job.builderType.toName(setterName); for (JavacNode child : job.builderType.down()) { diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 50193f99..b5bc73fb 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -777,7 +777,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { arg = maker.Conditional(eqNull, emptyCollection, tgt[1]); } - String setterName = HandlerUtil.buildAccessorName(setterPrefix, bfd.name.toString()); + String setterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, bfd.name.toString()); JCMethodInvocation apply = maker.Apply(List.nil(), maker.Select(maker.Ident(job.toName(BUILDER_VARIABLE_NAME)), job.toName(setterName)), List.of(arg)); JCExpressionStatement exec = maker.Exec(apply); return exec; @@ -949,7 +949,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { } private void generateSimpleSetterMethodForBuilder(SuperBuilderJob job, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JCExpression returnType, JCStatement returnStatement, List annosOnParam, JavacNode originalFieldNode, String setterPrefix) { - String setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString()); + String setterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, paramName.toString()); Name setterName_ = job.builderType.toName(setterName); for (JavacNode child : job.builderType.down()) { diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index 4ca09b82..77fcd4ea 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -300,7 +300,7 @@ public class JavacSingularsRecipes { ListBuffer statements = new ListBuffer(); statements.append(clearStatement); - Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString())); + Name methodName = builderType.toName(HandlerUtil.buildAccessorName(source, "clear", data.getPluralName().toString())); finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.nil(), List.nil(), access, null); } @@ -312,7 +312,7 @@ public class JavacSingularsRecipes { Name name = data.getSingularName(); String setterPrefix = data.getSetterPrefix(); if (setterPrefix.isEmpty() && !fluent) setterPrefix = getAddMethodName(); - if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(setterPrefix, name.toString())); + if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(source, setterPrefix, name.toString())); statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source)); List methodAnnotations = copyAnnotations(findCopyableToBuilderSingularSetterAnnotations(data.annotation.up())); @@ -344,7 +344,7 @@ public class JavacSingularsRecipes { Name name = data.getPluralName(); String setterPrefix = data.getSetterPrefix(); if (setterPrefix.isEmpty() && !fluent) setterPrefix = getAddMethodName() + "All"; - if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(setterPrefix, name.toString())); + if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(source, setterPrefix, name.toString())); JCExpression paramType = getPluralMethodParamType(builderType); paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs(), source); long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext()); diff --git a/test/transform/resource/after-delombok/BuilderWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/BuilderWithJavaBeansSpecCapitalization.java new file mode 100644 index 00000000..4a21f2c3 --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderWithJavaBeansSpecCapitalization.java @@ -0,0 +1,106 @@ +class BuilderWithJavaBeansSpecCapitalization { + java.util.List a; + java.util.List aField; + String bField; + @java.lang.SuppressWarnings("all") + BuilderWithJavaBeansSpecCapitalization(final java.util.List a, final java.util.List aField, final String bField) { + this.a = a; + this.aField = aField; + this.bField = bField; + } + @java.lang.SuppressWarnings("all") + public static class BuilderWithJavaBeansSpecCapitalizationBuilder { + @java.lang.SuppressWarnings("all") + private java.util.ArrayList a; + @java.lang.SuppressWarnings("all") + private java.util.ArrayList aField; + @java.lang.SuppressWarnings("all") + private String bField; + @java.lang.SuppressWarnings("all") + BuilderWithJavaBeansSpecCapitalizationBuilder() { + } + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setZ(final String z) { + if (this.a == null) this.a = new java.util.ArrayList(); + this.a.add(z); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setA(final java.util.Collection a) { + if (a == null) { + throw new java.lang.NullPointerException("a cannot be null"); + } + if (this.a == null) this.a = new java.util.ArrayList(); + this.a.addAll(a); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder clearA() { + if (this.a != null) this.a.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setyField(final String yField) { + if (this.aField == null) this.aField = new java.util.ArrayList(); + this.aField.add(yField); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setaField(final java.util.Collection aField) { + if (aField == null) { + throw new java.lang.NullPointerException("aField cannot be null"); + } + if (this.aField == null) this.aField = new java.util.ArrayList(); + this.aField.addAll(aField); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder clearaField() { + if (this.aField != null) this.aField.clear(); + return this; + } + /** + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setbField(final String bField) { + this.bField = bField; + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderWithJavaBeansSpecCapitalization build() { + java.util.List a; + switch (this.a == null ? 0 : this.a.size()) { + case 0: + a = java.util.Collections.emptyList(); + break; + case 1: + a = java.util.Collections.singletonList(this.a.get(0)); + break; + default: + a = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.a)); + } + java.util.List aField; + switch (this.aField == null ? 0 : this.aField.size()) { + case 0: + aField = java.util.Collections.emptyList(); + break; + case 1: + aField = java.util.Collections.singletonList(this.aField.get(0)); + break; + default: + aField = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.aField)); + } + return new BuilderWithJavaBeansSpecCapitalization(a, aField, this.bField); + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder(a=" + this.a + ", aField=" + this.aField + ", bField=" + this.bField + ")"; + } + } + @java.lang.SuppressWarnings("all") + public static BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder builder() { + return new BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder(); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/GetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/GetterWithJavaBeansSpecCapitalization.java index 06026c1b..51ccfe63 100644 --- a/test/transform/resource/after-delombok/GetterWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/after-delombok/GetterWithJavaBeansSpecCapitalization.java @@ -1,17 +1,3 @@ -class GetterWithoutJavaBeansSpecCapitalization { - int a; - int aField; - @java.lang.SuppressWarnings("all") - public int getA() { - return this.a; - } - @java.lang.SuppressWarnings("all") - public int getAField() { - return this.aField; - } -} - - class GetterWithJavaBeansSpecCapitalization { int a; int aField; @@ -23,6 +9,4 @@ class GetterWithJavaBeansSpecCapitalization { public int getaField() { return this.aField; } -} - - +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/SetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/SetterWithJavaBeansSpecCapitalization.java index 24c8e883..de68ee60 100644 --- a/test/transform/resource/after-delombok/SetterWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/after-delombok/SetterWithJavaBeansSpecCapitalization.java @@ -1,16 +1,3 @@ -class SetterWithoutJavaBeansSpecCapitalization { - int a; - int aField; - @java.lang.SuppressWarnings("all") - public void setA(final int a) { - this.a = a; - } - @java.lang.SuppressWarnings("all") - public void setAField(final int aField) { - this.aField = aField; - } -} - class SetterWithJavaBeansSpecCapitalization { int a; int aField; @@ -23,5 +10,3 @@ class SetterWithJavaBeansSpecCapitalization { this.aField = aField; } } - - diff --git a/test/transform/resource/after-delombok/ValueWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/ValueWithJavaBeansSpecCapitalization.java index 20139baf..b92dd5b6 100644 --- a/test/transform/resource/after-delombok/ValueWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/after-delombok/ValueWithJavaBeansSpecCapitalization.java @@ -1,16 +1,13 @@ final class ValueWithJavaBeansSpecCapitalization { private final int aField; - @java.lang.SuppressWarnings("all") public ValueWithJavaBeansSpecCapitalization(final int aField) { this.aField = aField; } - @java.lang.SuppressWarnings("all") public int getaField() { return this.aField; } - @java.lang.Override @java.lang.SuppressWarnings("all") public boolean equals(final java.lang.Object o) { @@ -20,7 +17,6 @@ final class ValueWithJavaBeansSpecCapitalization { if (this.getaField() != other.getaField()) return false; return true; } - @java.lang.Override @java.lang.SuppressWarnings("all") public int hashCode() { @@ -29,27 +25,22 @@ final class ValueWithJavaBeansSpecCapitalization { result = result * PRIME + this.getaField(); return result; } - @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { return "ValueWithJavaBeansSpecCapitalization(aField=" + this.getaField() + ")"; } } - final class ValueWithoutJavaBeansSpecCapitalization { private final int aField; - @java.lang.SuppressWarnings("all") public ValueWithoutJavaBeansSpecCapitalization(final int aField) { this.aField = aField; } - @java.lang.SuppressWarnings("all") public int getAField() { return this.aField; } - @java.lang.Override @java.lang.SuppressWarnings("all") public boolean equals(final java.lang.Object o) { @@ -59,7 +50,6 @@ final class ValueWithoutJavaBeansSpecCapitalization { if (this.getAField() != other.getAField()) return false; return true; } - @java.lang.Override @java.lang.SuppressWarnings("all") public int hashCode() { @@ -68,7 +58,6 @@ final class ValueWithoutJavaBeansSpecCapitalization { result = result * PRIME + this.getAField(); return result; } - @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { diff --git a/test/transform/resource/after-delombok/WithOnJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/WithOnJavaBeansSpecCapitalization.java deleted file mode 100644 index afed2f0e..00000000 --- a/test/transform/resource/after-delombok/WithOnJavaBeansSpecCapitalization.java +++ /dev/null @@ -1,29 +0,0 @@ -class WithOnJavaBeansSpecCapitalization { - int aField; - - WithOnJavaBeansSpecCapitalization(int aField) { - } - - /** - * @return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed). - */ - @java.lang.SuppressWarnings("all") - public WithOnJavaBeansSpecCapitalization withaField(final int aField) { - return this.aField == aField ? this : new WithOnJavaBeansSpecCapitalization(aField); - } -} - -class WithOffJavaBeansSpecCapitalization { - int aField; - - WithOffJavaBeansSpecCapitalization(int aField) { - } - - /** - * @return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed). - */ - @java.lang.SuppressWarnings("all") - public WithOffJavaBeansSpecCapitalization withAField(final int aField) { - return this.aField == aField ? this : new WithOffJavaBeansSpecCapitalization(aField); - } -} diff --git a/test/transform/resource/after-delombok/WithWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/WithWithJavaBeansSpecCapitalization.java new file mode 100644 index 00000000..e3737848 --- /dev/null +++ b/test/transform/resource/after-delombok/WithWithJavaBeansSpecCapitalization.java @@ -0,0 +1,12 @@ +class WithWithJavaBeansSpecCapitalization { + int aField; + WithWithJavaBeansSpecCapitalization(int aField) { + } + /** + * @return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed). + */ + @java.lang.SuppressWarnings("all") + public WithWithJavaBeansSpecCapitalization withaField(final int aField) { + return this.aField == aField ? this : new WithWithJavaBeansSpecCapitalization(aField); + } +} diff --git a/test/transform/resource/after-ecj/BuilderWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/BuilderWithJavaBeansSpecCapitalization.java new file mode 100644 index 00000000..1107254f --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderWithJavaBeansSpecCapitalization.java @@ -0,0 +1,99 @@ +@lombok.Builder(setterPrefix = "set") class BuilderWithJavaBeansSpecCapitalization { + public static @java.lang.SuppressWarnings("all") class BuilderWithJavaBeansSpecCapitalizationBuilder { + private @java.lang.SuppressWarnings("all") java.util.ArrayList a; + private @java.lang.SuppressWarnings("all") java.util.ArrayList aField; + private @java.lang.SuppressWarnings("all") String bField; + @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalizationBuilder() { + super(); + } + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setZ(final String z) { + if ((this.a == null)) + this.a = new java.util.ArrayList(); + this.a.add(z); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setA(final java.util.Collection a) { + if ((a == null)) + { + throw new java.lang.NullPointerException("a cannot be null"); + } + if ((this.a == null)) + this.a = new java.util.ArrayList(); + this.a.addAll(a); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder clearA() { + if ((this.a != null)) + this.a.clear(); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setyField(final String yField) { + if ((this.aField == null)) + this.aField = new java.util.ArrayList(); + this.aField.add(yField); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setaField(final java.util.Collection aField) { + if ((aField == null)) + { + throw new java.lang.NullPointerException("aField cannot be null"); + } + if ((this.aField == null)) + this.aField = new java.util.ArrayList(); + this.aField.addAll(aField); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder clearaField() { + if ((this.aField != null)) + this.aField.clear(); + return this; + } + /** + * @return {@code this}. + */ + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder setbField(final String bField) { + this.bField = bField; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization build() { + java.util.List a; + switch (((this.a == null) ? 0 : this.a.size())) { + case 0 : + a = java.util.Collections.emptyList(); + break; + case 1 : + a = java.util.Collections.singletonList(this.a.get(0)); + break; + default : + a = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.a)); + } + java.util.List aField; + switch (((this.aField == null) ? 0 : this.aField.size())) { + case 0 : + aField = java.util.Collections.emptyList(); + break; + case 1 : + aField = java.util.Collections.singletonList(this.aField.get(0)); + break; + default : + aField = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.aField)); + } + return new BuilderWithJavaBeansSpecCapitalization(a, aField, this.bField); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (((((("BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder(a=" + this.a) + ", aField=") + this.aField) + ", bField=") + this.bField) + ")"); + } + } + @lombok.Singular("z") java.util.List a; + @lombok.Singular("yField") java.util.List aField; + String bField; + @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization(final java.util.List a, final java.util.List aField, final String bField) { + super(); + this.a = a; + this.aField = aField; + this.bField = bField; + } + public static @java.lang.SuppressWarnings("all") BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder builder() { + return new BuilderWithJavaBeansSpecCapitalization.BuilderWithJavaBeansSpecCapitalizationBuilder(); + } +} diff --git a/test/transform/resource/after-ecj/GetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/GetterWithJavaBeansSpecCapitalization.java index d605b4ac..745529a0 100644 --- a/test/transform/resource/after-ecj/GetterWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/after-ecj/GetterWithJavaBeansSpecCapitalization.java @@ -1,33 +1,13 @@ -class GetterWithoutJavaBeansSpecCapitalization { +class GetterWithJavaBeansSpecCapitalization { @lombok.Getter int a; @lombok.Getter int aField; - - GetterWithoutJavaBeansSpecCapitalization() { - super(); - } - - public @java.lang.SuppressWarnings("all") int getA() { - return this.a; - } - - public @java.lang.SuppressWarnings("all") int getAField() { - return this.aField; - } -} - -@lombok.experimental.Accessors(javaBeansSpecCapitalization = true) class GetterWithJavaBeansSpecCapitalization { - @lombok.Getter int a; - @lombok.Getter int aField; - GetterWithJavaBeansSpecCapitalization() { super(); } - public @java.lang.SuppressWarnings("all") int getA() { return this.a; } - public @java.lang.SuppressWarnings("all") int getaField() { return this.aField; } -} +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/SetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/SetterWithJavaBeansSpecCapitalization.java index 9907621f..4e99890a 100644 --- a/test/transform/resource/after-ecj/SetterWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/after-ecj/SetterWithJavaBeansSpecCapitalization.java @@ -1,33 +1,13 @@ -class SetterWithoutJavaBeansSpecCapitalization { +class SetterWithJavaBeansSpecCapitalization { @lombok.Setter int a; @lombok.Setter int aField; - - SetterWithoutJavaBeansSpecCapitalization() { - super(); - } - - public @java.lang.SuppressWarnings("all") void setA(final int a) { - this.a = a; - } - - public @java.lang.SuppressWarnings("all") void setAField(final int aField) { - this.aField = aField; - } -} - -@lombok.experimental.Accessors(javaBeansSpecCapitalization = true) class SetterWithJavaBeansSpecCapitalization { - @lombok.Setter int a; - @lombok.Setter int aField; - SetterWithJavaBeansSpecCapitalization() { super(); } - public @java.lang.SuppressWarnings("all") void setA(final int a) { this.a = a; } - public @java.lang.SuppressWarnings("all") void setaField(final int aField) { this.aField = aField; } -} +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValueWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/ValueWithJavaBeansSpecCapitalization.java index f41fcf58..8117dbb0 100644 --- a/test/transform/resource/after-ecj/ValueWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/after-ecj/ValueWithJavaBeansSpecCapitalization.java @@ -1,4 +1,4 @@ -final @lombok.Value @lombok.experimental.Accessors(javaBeansSpecCapitalization = true) class ValueWithJavaBeansSpecCapitalization { +final @lombok.Value class ValueWithJavaBeansSpecCapitalization { private final int aField; public @java.lang.SuppressWarnings("all") int getaField() { return this.aField; @@ -27,32 +27,3 @@ final @lombok.Value @lombok.experimental.Accessors(javaBeansSpecCapitalization = this.aField = aField; } } -final @lombok.Value class ValueWithoutJavaBeansSpecCapitalization { - private final int aField; - public @java.lang.SuppressWarnings("all") int getAField() { - return this.aField; - } - public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { - if ((o == this)) - return true; - if ((! (o instanceof ValueWithoutJavaBeansSpecCapitalization))) - return false; - final ValueWithoutJavaBeansSpecCapitalization other = (ValueWithoutJavaBeansSpecCapitalization) o; - if ((this.getAField() != other.getAField())) - return false; - return true; - } - public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { - final int PRIME = 59; - int result = 1; - result = ((result * PRIME) + this.getAField()); - return result; - } - public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { - return (("ValueWithoutJavaBeansSpecCapitalization(aField=" + this.getAField()) + ")"); - } - public @java.lang.SuppressWarnings("all") ValueWithoutJavaBeansSpecCapitalization(final int aField) { - super(); - this.aField = aField; - } -} diff --git a/test/transform/resource/after-ecj/WithOnJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/WithOnJavaBeansSpecCapitalization.java deleted file mode 100644 index 06164fe9..00000000 --- a/test/transform/resource/after-ecj/WithOnJavaBeansSpecCapitalization.java +++ /dev/null @@ -1,25 +0,0 @@ -@lombok.With @lombok.experimental.Accessors(javaBeansSpecCapitalization = true) class WithOnJavaBeansSpecCapitalization { - int aField; - WithOnJavaBeansSpecCapitalization(int aField) { - super(); - } - /** - * @return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed). - */ - public @java.lang.SuppressWarnings("all") WithOnJavaBeansSpecCapitalization withaField(final int aField) { - return ((this.aField == aField) ? this : new WithOnJavaBeansSpecCapitalization(aField)); - } -} - -@lombok.With class WithOffJavaBeansSpecCapitalization { - int aField; - WithOffJavaBeansSpecCapitalization(int aField) { - super(); - } - /** - * @return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed). - */ - public @java.lang.SuppressWarnings("all") WithOffJavaBeansSpecCapitalization withAField(final int aField) { - return ((this.aField == aField) ? this : new WithOffJavaBeansSpecCapitalization(aField)); - } -} diff --git a/test/transform/resource/after-ecj/WithWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/WithWithJavaBeansSpecCapitalization.java new file mode 100644 index 00000000..d530ad8a --- /dev/null +++ b/test/transform/resource/after-ecj/WithWithJavaBeansSpecCapitalization.java @@ -0,0 +1,12 @@ +@lombok.With class WithOnJavaBeansSpecCapitalization { + int aField; + WithWithJavaBeansSpecCapitalization(int aField) { + super(); + } + /** + * @return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed). + */ + public @java.lang.SuppressWarnings("all") WithWithJavaBeansSpecCapitalization withaField(final int aField) { + return ((this.aField == aField) ? this : new WithWithJavaBeansSpecCapitalization(aField)); + } +} diff --git a/test/transform/resource/before/BuilderWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/BuilderWithJavaBeansSpecCapitalization.java new file mode 100644 index 00000000..db1fe15f --- /dev/null +++ b/test/transform/resource/before/BuilderWithJavaBeansSpecCapitalization.java @@ -0,0 +1,7 @@ +//CONF: lombok.accessors.capitalization = beanspec +@lombok.Builder(setterPrefix = "set") +class BuilderWithJavaBeansSpecCapitalization { + @lombok.Singular("z") java.util.List a; + @lombok.Singular("yField") java.util.List aField; + String bField; +} diff --git a/test/transform/resource/before/GetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/GetterWithJavaBeansSpecCapitalization.java index 3c27317c..68f41e3d 100644 --- a/test/transform/resource/before/GetterWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/before/GetterWithJavaBeansSpecCapitalization.java @@ -1,11 +1,5 @@ -class GetterWithoutJavaBeansSpecCapitalization { - @lombok.Getter int a; - @lombok.Getter int aField; -} - -@lombok.experimental.Accessors(javaBeansSpecCapitalization=true) +//CONF: lombok.accessors.capitalization = beanspec class GetterWithJavaBeansSpecCapitalization { @lombok.Getter int a; @lombok.Getter int aField; } - diff --git a/test/transform/resource/before/SetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/SetterWithJavaBeansSpecCapitalization.java index 80a1b4ee..b5e34ba7 100644 --- a/test/transform/resource/before/SetterWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/before/SetterWithJavaBeansSpecCapitalization.java @@ -1,11 +1,5 @@ -class SetterWithoutJavaBeansSpecCapitalization { - @lombok.Setter int a; - @lombok.Setter int aField; -} - -@lombok.experimental.Accessors(javaBeansSpecCapitalization=true) +//CONF: lombok.accessors.capitalization = beanspec class SetterWithJavaBeansSpecCapitalization { @lombok.Setter int a; @lombok.Setter int aField; } - diff --git a/test/transform/resource/before/ValueWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/ValueWithJavaBeansSpecCapitalization.java index f0044ed9..7c001f6e 100644 --- a/test/transform/resource/before/ValueWithJavaBeansSpecCapitalization.java +++ b/test/transform/resource/before/ValueWithJavaBeansSpecCapitalization.java @@ -1,10 +1,5 @@ +//CONF: lombok.accessors.capitalization = beanspec @lombok.Value -@lombok.experimental.Accessors(javaBeansSpecCapitalization = true) class ValueWithJavaBeansSpecCapitalization { final int aField; } - -@lombok.Value -class ValueWithoutJavaBeansSpecCapitalization { - final int aField; -} diff --git a/test/transform/resource/before/WithOnJavaBeansSpecCapitalization.java b/test/transform/resource/before/WithOnJavaBeansSpecCapitalization.java deleted file mode 100644 index 476fb5a4..00000000 --- a/test/transform/resource/before/WithOnJavaBeansSpecCapitalization.java +++ /dev/null @@ -1,16 +0,0 @@ -@lombok.With -@lombok.experimental.Accessors(javaBeansSpecCapitalization = true) -class WithOnJavaBeansSpecCapitalization { - int aField; - - WithOnJavaBeansSpecCapitalization(int aField) { - } -} - -@lombok.With -class WithOffJavaBeansSpecCapitalization { - int aField; - - WithOffJavaBeansSpecCapitalization(int aField) { - } -} diff --git a/test/transform/resource/before/WithWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/WithWithJavaBeansSpecCapitalization.java new file mode 100644 index 00000000..ef4a78ad --- /dev/null +++ b/test/transform/resource/before/WithWithJavaBeansSpecCapitalization.java @@ -0,0 +1,8 @@ +//CONF: lombok.accessors.capitalization = beanspec +@lombok.With +class WithWithJavaBeansSpecCapitalization { + int aField; + + WithWithJavaBeansSpecCapitalization(int aField) { + } +} -- cgit From 1d7db8c4dfa2f7a26d9816398947f6e76e506093 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Fri, 22 Oct 2021 10:15:29 +0200 Subject: [fixes #2995] Skip records for field defaults via config --- src/core/lombok/eclipse/handlers/HandleFieldDefaults.java | 2 ++ src/core/lombok/javac/handlers/HandleFieldDefaults.java | 2 ++ .../after-delombok/FieldDefaultsViaConfigOnRecord.java | 3 +++ .../resource/after-ecj/FieldDefaultsViaConfigOnRecord.java | 10 ++++++++++ .../resource/before/FieldDefaultsViaConfigOnRecord.java | 7 +++++++ 5 files changed, 24 insertions(+) create mode 100644 test/transform/resource/after-delombok/FieldDefaultsViaConfigOnRecord.java create mode 100644 test/transform/resource/after-ecj/FieldDefaultsViaConfigOnRecord.java create mode 100644 test/transform/resource/before/FieldDefaultsViaConfigOnRecord.java (limited to 'src/core/lombok/eclipse') diff --git a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java index 5900e7ed..3297ba06 100644 --- a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java @@ -160,6 +160,8 @@ public class HandleFieldDefaults extends EclipseASTAdapter { boolean defaultToFinal = makeFinalIsExplicit ? false : Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.FIELD_DEFAULTS_FINAL_EVERYWHERE)); if (!defaultToPrivate && !defaultToFinal && fieldDefaults == null) return; + // Do not apply field defaults to records if set using the the config system + if (fieldDefaults == null && !isClassOrEnum(typeNode)) return; AccessLevel fdAccessLevel = (fieldDefaults != null && levelIsExplicit) ? fd.level() : defaultToPrivate ? AccessLevel.PRIVATE : null; boolean fdToFinal = (fieldDefaults != null && makeFinalIsExplicit) ? fd.makeFinal() : defaultToFinal; diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java index ebab67e3..9a6632dd 100644 --- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java @@ -140,6 +140,8 @@ public class HandleFieldDefaults extends JavacASTAdapter { boolean defaultToFinal = makeFinalIsExplicit ? false : Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.FIELD_DEFAULTS_FINAL_EVERYWHERE)); if (!defaultToPrivate && !defaultToFinal && fieldDefaults == null) return; + // Do not apply field defaults to records if set using the the config system + if (fieldDefaults == null && !isClassOrEnum(typeNode)) return; AccessLevel fdAccessLevel = (fieldDefaults != null && levelIsExplicit) ? fd.level() : defaultToPrivate ? AccessLevel.PRIVATE : null; boolean fdToFinal = (fieldDefaults != null && makeFinalIsExplicit) ? fd.makeFinal() : defaultToFinal; diff --git a/test/transform/resource/after-delombok/FieldDefaultsViaConfigOnRecord.java b/test/transform/resource/after-delombok/FieldDefaultsViaConfigOnRecord.java new file mode 100644 index 00000000..1a2ce882 --- /dev/null +++ b/test/transform/resource/after-delombok/FieldDefaultsViaConfigOnRecord.java @@ -0,0 +1,3 @@ +// version 14: +public record FieldDefaultsViaConfigOnRecord(String a, String b) { +} diff --git a/test/transform/resource/after-ecj/FieldDefaultsViaConfigOnRecord.java b/test/transform/resource/after-ecj/FieldDefaultsViaConfigOnRecord.java new file mode 100644 index 00000000..44ef0d4c --- /dev/null +++ b/test/transform/resource/after-ecj/FieldDefaultsViaConfigOnRecord.java @@ -0,0 +1,10 @@ +// version 14: +public record FieldDefaultsViaConfigOnRecord(String a, String b) { +/* Implicit */ private final String a; +/* Implicit */ private final String b; + public FieldDefaultsViaConfigOnRecord(String a, String b) { + super(); + .a = a; + .b = b; + } +} \ No newline at end of file diff --git a/test/transform/resource/before/FieldDefaultsViaConfigOnRecord.java b/test/transform/resource/before/FieldDefaultsViaConfigOnRecord.java new file mode 100644 index 00000000..e72179e9 --- /dev/null +++ b/test/transform/resource/before/FieldDefaultsViaConfigOnRecord.java @@ -0,0 +1,7 @@ +// version 14: +//CONF: lombok.fieldDefaults.defaultFinal = true +//CONF: lombok.fieldDefaults.defaultPrivate = true +//unchanged + +public record FieldDefaultsViaConfigOnRecord(String a, String b) { +} \ No newline at end of file -- cgit From 3a0176fd907ec594194cabf843a5681fd7b811fd Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 26 Oct 2021 04:14:46 +0200 Subject: [fixes #3014] Detecting whether inner classes are static wouldn't work if placed inside an enum or interface. --- src/core/lombok/eclipse/EclipseNode.java | 9 ++- src/core/lombok/javac/JavacNode.java | 8 ++- test/core/src/lombok/DirectoryRunner.java | 1 - .../after-delombok/BuilderNestedInEnum.java | 70 ++++++++++++++++++++++ .../resource/after-ecj/BuilderNestedInEnum.java | 68 +++++++++++++++++++++ 5 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 test/transform/resource/after-delombok/BuilderNestedInEnum.java create mode 100644 test/transform/resource/after-ecj/BuilderNestedInEnum.java (limited to 'src/core/lombok/eclipse') diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java index 4f86f0a5..4950aeef 100644 --- a/src/core/lombok/eclipse/EclipseNode.java +++ b/src/core/lombok/eclipse/EclipseNode.java @@ -215,13 +215,16 @@ public class EclipseNode extends lombok.core.LombokNode DEBUG_FOCUS_ON_FILE = Arrays.asList( - "BuilderNestedInEnum.java" ); public enum Compiler { diff --git a/test/transform/resource/after-delombok/BuilderNestedInEnum.java b/test/transform/resource/after-delombok/BuilderNestedInEnum.java new file mode 100644 index 00000000..26dc2a06 --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderNestedInEnum.java @@ -0,0 +1,70 @@ +class BuilderNestedInEnum { + public enum TestEnum { + FOO, BAR; + public static final class TestBuilder { + private final String field; + @java.lang.SuppressWarnings("all") + TestBuilder(final String field) { + this.field = field; + } + @java.lang.SuppressWarnings("all") + public static class TestBuilderBuilder { + @java.lang.SuppressWarnings("all") + private String field; + @java.lang.SuppressWarnings("all") + TestBuilderBuilder() { + } + /** + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + public BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder field(final String field) { + this.field = field; + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderNestedInEnum.TestEnum.TestBuilder build() { + return new BuilderNestedInEnum.TestEnum.TestBuilder(this.field); + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder(field=" + this.field + ")"; + } + } + @java.lang.SuppressWarnings("all") + public static BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder builder() { + return new BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder(); + } + @java.lang.SuppressWarnings("all") + public String getField() { + return this.field; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof BuilderNestedInEnum.TestEnum.TestBuilder)) return false; + final BuilderNestedInEnum.TestEnum.TestBuilder other = (BuilderNestedInEnum.TestEnum.TestBuilder) o; + final java.lang.Object this$field = this.getField(); + final java.lang.Object other$field = other.getField(); + if (this$field == null ? other$field != null : !this$field.equals(other$field)) return false; + return true; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + final java.lang.Object $field = this.getField(); + result = result * PRIME + ($field == null ? 43 : $field.hashCode()); + return result; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderNestedInEnum.TestEnum.TestBuilder(field=" + this.getField() + ")"; + } + } + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/BuilderNestedInEnum.java b/test/transform/resource/after-ecj/BuilderNestedInEnum.java new file mode 100644 index 00000000..b3fb54f3 --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderNestedInEnum.java @@ -0,0 +1,68 @@ +class BuilderNestedInEnum { + public enum TestEnum { + public static final @lombok.Builder @lombok.Value class TestBuilder { + public static @java.lang.SuppressWarnings("all") class TestBuilderBuilder { + private @java.lang.SuppressWarnings("all") String field; + @java.lang.SuppressWarnings("all") TestBuilderBuilder() { + super(); + } + /** + * @return {@code this}. + */ + public @java.lang.SuppressWarnings("all") BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder field(final String field) { + this.field = field; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderNestedInEnum.TestEnum.TestBuilder build() { + return new BuilderNestedInEnum.TestEnum.TestBuilder(this.field); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder(field=" + this.field) + ")"); + } + } + private final String field; + @java.lang.SuppressWarnings("all") TestBuilder(final String field) { + super(); + this.field = field; + } + public static @java.lang.SuppressWarnings("all") BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder builder() { + return new BuilderNestedInEnum.TestEnum.TestBuilder.TestBuilderBuilder(); + } + public @java.lang.SuppressWarnings("all") String getField() { + return this.field; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof BuilderNestedInEnum.TestEnum.TestBuilder))) + return false; + final BuilderNestedInEnum.TestEnum.TestBuilder other = (BuilderNestedInEnum.TestEnum.TestBuilder) o; + final java.lang.Object this$field = this.getField(); + final java.lang.Object other$field = other.getField(); + if (((this$field == null) ? (other$field != null) : (! this$field.equals(other$field)))) + return false; + return true; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + final int PRIME = 59; + int result = 1; + final java.lang.Object $field = this.getField(); + result = ((result * PRIME) + (($field == null) ? 43 : $field.hashCode())); + return result; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("BuilderNestedInEnum.TestEnum.TestBuilder(field=" + this.getField()) + ")"); + } + } + FOO(), + BAR(), + () { + } + public TestEnum() { + super(); + } + } + BuilderNestedInEnum() { + super(); + } +} \ No newline at end of file -- cgit