diff options
46 files changed, 711 insertions, 145 deletions
@@ -20,6 +20,7 @@ Jan Matèrne <jhm@apache.org> Jan Rieke <it@janrieke.de> Jappe van der Hel <jappe.vanderhel@gmail.com> John Paul Taylor II <johnpaultaylorii@gmail.com> +Karthik kathari <44122128+varkart@users.noreply.github.com> Kevin Chirls <kchirls@users.noreply.github.com> Liu DongMiao <liudongmiao@gmail.com> Luan Nico <luannico27@gmail.com> diff --git a/buildScripts/compile.ant.xml b/buildScripts/compile.ant.xml index 23a8a63c..e4283c29 100644 --- a/buildScripts/compile.ant.xml +++ b/buildScripts/compile.ant.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2020-2021 The Project Lombok Authors. + Copyright (C) 2020-2022 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 @@ -74,7 +74,21 @@ This buildfile is part of projectlombok.org. It takes care of compiling and buil </jar> </target> - <target name="compile" depends="version, deps, -setup.build, create.spiProcessor" description="Compiles the code"> + <target name="create.mavenEcjBootstrapAgent" depends="-setup.build" description="Compiles the Maven ECJ bootstrap agent"> + <ivy:compile destdir="build/mavenEcjBootstrapAgent" source="1.6" target="1.6" ecj="true"> + <bootclasspath path="${jdk6-rt.loc}" /> + <src path="src/mavenEcjBootstrapAgent" /> + </ivy:compile> + <mkdir dir="build/lombok-main/lombok/launch" /> + <jar destfile="build/lombok-main/lombok/launch/mavenEcjBootstrapAgent.jar" basedir="build/mavenEcjBootstrapAgent"> + <manifest> + <attribute name="Premain-Class" value="lombok.launch.AgentBootstrap" /> + <attribute name="Can-Redefine-Classes" value="true" /> + </manifest> + </jar> + </target> + + <target name="compile" depends="version, deps, -setup.build, create.spiProcessor, create.agentBootstrap" description="Compiles the code"> <!-- 1. Compile stubs. 2. Compile transplants. diff --git a/buildScripts/create-eclipse-project.ant.xml b/buildScripts/create-eclipse-project.ant.xml index b0f5fcca..f9c45bc6 100644 --- a/buildScripts/create-eclipse-project.ant.xml +++ b/buildScripts/create-eclipse-project.ant.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2010-2021 The Project Lombok Authors. + Copyright (C) 2010-2022 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 @@ -34,6 +34,7 @@ This buildfile is part of projectlombok.org. It creates the infrastructure neede <srcdir dir="src/launch" /> <srcdir dir="src/utils" /> <srcdir dir="src/eclipseAgent" /> + <srcdir dir="src/mavenEcjBootstrapAgent" /> <srcdir dir="src/installer" /> <srcdir dir="src/delombok" /> <srcdir dir="src/stubs" srcout="bin/stubs" /> diff --git a/buildScripts/create-intellij-project.ant.xml b/buildScripts/create-intellij-project.ant.xml index f0bba6e4..3a5398dd 100644 --- a/buildScripts/create-intellij-project.ant.xml +++ b/buildScripts/create-intellij-project.ant.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2010-2021 The Project Lombok Authors. + Copyright (C) 2010-2022 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 @@ -45,6 +45,7 @@ This buildfile is part of projectlombok.org. It creates the infrastructure neede <srcdir dir="src/launch" /> <srcdir dir="src/utils" /> <srcdir dir="src/eclipseAgent" /> + <srcdir dir="src/mavenEcjBootstrapAgent" /> <srcdir dir="src/installer" /> <srcdir dir="src/delombok" /> <srcdir dir="src/stubs" /> diff --git a/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.40.xml b/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.44.xml index 11302b2b..298d465d 100644 --- a/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.40.xml +++ b/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.44.xml @@ -1,5 +1,5 @@ <ivy-module version="2.0"> - <info organisation="org.projectlombok" module="lombok.patcher" revision="0.40" publication="20201015232000"> + <info organisation="org.projectlombok" module="lombok.patcher" revision="0.44" publication="20220317220900"> <license name="MIT License" url="https://www.opensource.org/licenses/mit-license.php" /> <ivyauthor name="rzwitserloot" url="https://github.com/rzwitserloot" /> <ivyauthor name="rspilker" url="https://github.com/rspilker" /> @@ -9,6 +9,6 @@ <conf name="default" /> </configurations> <publications> - <artifact conf="default" url="https://projectlombok.org/downloads/lombok.patcher-0.40.jar" /> + <artifact conf="default" url="https://projectlombok.org/downloads/lombok.patcher-0.44.jar" /> </publications> </ivy-module> diff --git a/buildScripts/ivy.xml b/buildScripts/ivy.xml index d12f8867..afd799d0 100644 --- a/buildScripts/ivy.xml +++ b/buildScripts/ivy.xml @@ -37,7 +37,7 @@ </configurations> <dependencies> - <dependency org="org.projectlombok" name="lombok.patcher" rev="0.42" conf="build,stripe->default" /> + <dependency org="org.projectlombok" name="lombok.patcher" rev="0.44" conf="build,stripe->default" /> <dependency org="zwitserloot.com" name="cmdreader" rev="1.2" conf="build,stripe->runtime" /> <dependency org="org.apache.ant" name="ant" rev="1.10.5" conf="build->default" /> <dependency org="org.apache.ant" name="ant-junit" rev="1.10.5" conf="build->default" /> diff --git a/buildScripts/maven.ant.xml b/buildScripts/maven.ant.xml index 57bb6b99..fe64a611 100644 --- a/buildScripts/maven.ant.xml +++ b/buildScripts/maven.ant.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2020 The Project Lombok Authors. + Copyright (C) 2020-2022 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 @@ -43,6 +43,7 @@ This buildfile is part of projectlombok.org. It makes maven-compatible repositor <fileset dir="src/launch" /> <fileset dir="src/utils" /> <fileset dir="src/eclipseAgent" /> + <fileset dir="src/mavenEcjBootstrapAgent" /> <fileset dir="src/installer" /> <fileset dir="src/delombok" /> <fileset dir="test/transform/src" /> diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 0ba93306..435388e1 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -3,11 +3,19 @@ Lombok Changelog ### v1.18.23 "Edgy Guinea Pig" +* PLATFORM: JDK18 support added. [Issue #3129](https://github.com/projectlombok/lombok/issues/3129). +* PLATFORM: Using ecj and maven? There's now a [command line option to integrate lombok into your build chain](https://projectlombok.org/setup/ecj). [Issue #3143](https://github.com/projectlombok/lombok/issues/3143). * FEATURE: `@ToString` has an annotation parameter called `onlyExplicitlyIncluded`. There's now a config key `lombok.toString.onlyExplicitlyIncluded` to set this property as well. [Issue #2849](https://github.com/projectlombok/lombok/pull/2849). * FEATURE: Turning a field named `uShape` into a getter is tricky: `getUShape` or `getuShape`? The community is split on which style to use. Lombok does `getUShape`, but if you prefer the `getuShape` style, add to `lombok.config`: `lombok.accessors.capitalization = beanspec`. [Issue #2693](https://github.com/projectlombok/lombok/issues/2693) [Pull Request #2996](https://github.com/projectlombok/lombok/pull/2996). Thanks __@YonathanSherwin__! -* FEATURE: You can now use `@Accessors(makeFinal = true)` to make `final` getters, setters, and with-ers. [Issue #1456](https://github.com/projectlombok/lombok/issues/1456) -* BUGFIX: Various save actions and refactor scripts in eclipse work better. [Issue #2995](https://github.com/projectlombok/lombok/issues/2995) [Issue #1309](https://github.com/projectlombok/lombok/issues/1309) [Issue #2985](https://github.com/projectlombok/lombok/issues/2985) [Issue #2509](https://github.com/projectlombok/lombok/issues/2509) -* BUGFIX: Eclipse projects using the jasperreports-plugin will now compile [Issue #1036](https://github.com/projectlombok/lombok/issues/1036) +* FEATURE: You can now use `@Accessors(makeFinal = true)` to make `final` getters, setters, and with-ers. [Issue #1456](https://github.com/projectlombok/lombok/issues/1456). +* BUGFIX: Various save actions and refactor scripts in eclipse work better. [Issue #2995](https://github.com/projectlombok/lombok/issues/2995) [Issue #1309](https://github.com/projectlombok/lombok/issues/1309) [Issue #2985](https://github.com/projectlombok/lombok/issues/2985) [Issue #2509](https://github.com/projectlombok/lombok/issues/2509). +* BUGFIX: Eclipse projects using the jasperreports-plugin will now compile. [Issue #1036](https://github.com/projectlombok/lombok/issues/1036). +* BUGFIX: inner classes in `@UtilityClass` classes were broken in JDK9+. [Issue #3097](https://github.com/projectlombok/lombok/issues/3097). +* BUGFIX: Delomboking code with `@Builder.Default` in it would generate different code vs lombok itself. [Issue #3053](https://github.com/projectlombok/lombok/issues/3053). +* BUGFIX: Combining `@NonNullByDefault` and `lombok.addNullAnnotations` would generate two `@Nullable` annotations and thus generate a compiler error. [Issue #3120](https://github.com/projectlombok/lombok/issues/3120). Thanks __@JohnPaulTaylorII__! +* BUGFIX: Null analysis in eclipse was broken for incremental builds. [Issue #3133](https://github.com/projectlombok/lombok/issues/3133). +* BUGFIX `VerifyError` would show up in the latest eclipse release when using various refactor scripts. [Issue #3134](https://github.com/projectlombok/lombok/issues/3134). +* BUGFIX: The various `@Log` annotations can now be placed on inner enums and records. [Issue #2990](https://github.com/projectlombok/lombok/issues/2990). * SECURITY: A widely reported security issue with log4j2 ([CVE-2021-44228](https://www.randori.com/blog/cve-2021-44228/)) has absolutely no effect on either lombok itself nor does usage of lombok on its own, or even the usage of lombok's `@Log4j2`, cause any issues whatsoever: You have to ship your own log4j2 dependency in your app - update that to 2.17 or otherwise mitigate this issue (see the CVE page). To avoid unneccessary warnings from dependency checkers, our dep on log4j2, which is used solely for testing, isn't shipped by us, and cannot be exploited in any way, has been updated to 2.17.1. [Issue #3063](https://github.com/projectlombok/lombok/issues/3063) * IMPROBABLE BREAKING CHANGE: Lombok now understands a few more annotations that imply "this field should not ever contain a null reference". Lombok will thus copy some of these new annotations e.g. to generated getters and the like. [Pull Request #2904](https://github.com/projectlombok/lombok/pull/2904) diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index c313cf51..072b6df2 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -2601,25 +2601,25 @@ public class EclipseHandlerUtil { applyAnnotationToMethodDecl(typeNode, mth, lib.getNonNullAnnotation(), lib.isTypeUse()); } - public static void createRelevantNullableAnnotation(EclipseNode typeNode, Argument arg) { + public static void createRelevantNullableAnnotation(EclipseNode typeNode, Argument arg, MethodDeclaration mth) { NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS); if (lib == null) return; - applyAnnotationToVarDecl(typeNode, arg, lib.getNullableAnnotation(), lib.isTypeUse()); + applyAnnotationToVarDecl(typeNode, arg, mth, lib.getNullableAnnotation(), lib.isTypeUse()); } - public static void createRelevantNullableAnnotation(EclipseNode typeNode, Argument arg, List<NullAnnotationLibrary> applied) { + public static void createRelevantNullableAnnotation(EclipseNode typeNode, Argument arg, MethodDeclaration mth, List<NullAnnotationLibrary> applied) { NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS); if (lib == null || applied.contains(lib)) return; - applyAnnotationToVarDecl(typeNode, arg, lib.getNullableAnnotation(), lib.isTypeUse()); + applyAnnotationToVarDecl(typeNode, arg, mth, lib.getNullableAnnotation(), lib.isTypeUse()); } - public static void createRelevantNonNullAnnotation(EclipseNode typeNode, Argument arg) { + public static void createRelevantNonNullAnnotation(EclipseNode typeNode, Argument arg, MethodDeclaration mth) { NullAnnotationLibrary lib = typeNode.getAst().readConfiguration(ConfigurationKeys.ADD_NULL_ANNOTATIONS); if (lib == null) return; - applyAnnotationToVarDecl(typeNode, arg, lib.getNonNullAnnotation(), lib.isTypeUse()); + applyAnnotationToVarDecl(typeNode, arg, mth, lib.getNonNullAnnotation(), lib.isTypeUse()); } private static void applyAnnotationToMethodDecl(EclipseNode typeNode, MethodDeclaration mth, String annType, boolean typeUse) { @@ -2653,9 +2653,10 @@ public class EclipseHandlerUtil { } a[0] = ann; mth.returnType.annotations[len - 1] = a; + mth.bits |= Eclipse.HasTypeAnnotations; } } - private static void applyAnnotationToVarDecl(EclipseNode typeNode, Argument arg, String annType, boolean typeUse) { + private static void applyAnnotationToVarDecl(EclipseNode typeNode, Argument arg, MethodDeclaration mth, String annType, boolean typeUse) { if (annType == null) return; int partCount = 1; @@ -2686,6 +2687,9 @@ public class EclipseHandlerUtil { } a[0] = ann; arg.type.annotations[len - 1] = a; + arg.type.bits |= Eclipse.HasTypeAnnotations; + arg.bits |= Eclipse.HasTypeAnnotations; + mth.bits |= Eclipse.HasTypeAnnotations; } } @@ -2770,15 +2774,7 @@ public class EclipseHandlerUtil { * 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; + return typeNode.isStatic() || typeNode.up() == null || typeNode.up().getKind() == Kind.COMPILATION_UNIT || isRecord(typeNode); } public static AbstractVariableDeclaration[] getRecordComponents(TypeDeclaration typeDeclaration) { diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index 998c1274..54f1a551 100755 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -44,6 +44,7 @@ import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.IfStatement; import org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.eclipse.jdt.internal.compiler.ast.MessageSend; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; @@ -430,7 +431,7 @@ public class EclipseSingularsRecipes { } } - protected void nullBehaviorize(EclipseNode typeNode, SingularData data, List<Statement> statements, Argument arg) { + protected void nullBehaviorize(EclipseNode typeNode, SingularData data, List<Statement> statements, Argument arg, MethodDeclaration md) { boolean ignoreNullCollections = data.isIgnoreNullCollections(); if (ignoreNullCollections) { @@ -439,11 +440,11 @@ public class EclipseSingularsRecipes { b.statements = statements.toArray(new Statement[statements.size()]); statements.clear(); statements.add(new IfStatement(isNotNull, b, 0, 0)); - EclipseHandlerUtil.createRelevantNullableAnnotation(typeNode, arg); + EclipseHandlerUtil.createRelevantNullableAnnotation(typeNode, arg, md); return; } - EclipseHandlerUtil.createRelevantNonNullAnnotation(typeNode, arg); + EclipseHandlerUtil.createRelevantNonNullAnnotation(typeNode, arg, md); Statement nullCheck = EclipseHandlerUtil.generateNullCheck(null, data.getPluralName(), typeNode, "%s cannot be null"); statements.add(0, nullCheck); } diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 940612e7..b0e0e526 100755 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -642,13 +642,17 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; QualifiedTypeReference objectRef = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] { p, p, p }); - if (onParamTypeNullable != null) objectRef.annotations = new Annotation[][] {null, null, onParamTypeNullable}; + if (onParamTypeNullable != null) { + objectRef.annotations = new Annotation[][] {null, null, onParamTypeNullable}; + objectRef.bits |= Eclipse.HasTypeAnnotations; + method.bits |= Eclipse.HasTypeAnnotations; + } setGeneratedBy(objectRef, source); method.arguments = new Argument[] {new Argument(new char[] { 'o' }, 0, objectRef, Modifier.FINAL)}; method.arguments[0].sourceStart = pS; method.arguments[0].sourceEnd = pE; if (!onParam.isEmpty() || onParamNullable != null) method.arguments[0].annotations = copyAnnotations(source, onParam.toArray(new Annotation[0]), onParamNullable); - EclipseHandlerUtil.createRelevantNullableAnnotation(type, method.arguments[0], applied); + EclipseHandlerUtil.createRelevantNullableAnnotation(type, method.arguments[0], method, applied); setGeneratedBy(method.arguments[0], source); List<Statement> statements = new ArrayList<Statement>(); @@ -898,7 +902,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH method.arguments = new Argument[] {new Argument(otherName, 0, objectRef, Modifier.FINAL)}; method.arguments[0].sourceStart = pS; method.arguments[0].sourceEnd = pE; if (!onParam.isEmpty()) method.arguments[0].annotations = onParam.toArray(new Annotation[0]); - EclipseHandlerUtil.createRelevantNullableAnnotation(type, method.arguments[0]); + EclipseHandlerUtil.createRelevantNullableAnnotation(type, method.arguments[0], method); setGeneratedBy(method.arguments[0], source); SingleNameReference otherRef = new SingleNameReference(otherName, p); diff --git a/src/core/lombok/eclipse/handlers/HandleWithBy.java b/src/core/lombok/eclipse/handlers/HandleWithBy.java index 5ab3cf81..bfba91d4 100644 --- a/src/core/lombok/eclipse/handlers/HandleWithBy.java +++ b/src/core/lombok/eclipse/handlers/HandleWithBy.java @@ -373,7 +373,7 @@ public class HandleWithBy extends EclipseAnnotationHandler<WithBy> { method.statements = statements.toArray(new Statement[0]); } - createRelevantNonNullAnnotation(sourceNode, param); + createRelevantNonNullAnnotation(sourceNode, param, method); createRelevantNonNullAnnotation(fieldNode, method); method.traverse(new SetGeneratedByVisitor(source), parent.scope); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index 47822ff3..a43e0331 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -207,7 +207,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs()); Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); - nullBehaviorize(builderType, data, statements, param); + nullBehaviorize(builderType, data, statements, param, md); if (returnStatement != null) statements.add(returnStatement); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index fbde3021..810a7878 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -184,7 +184,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs()); Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); - nullBehaviorize(builderType, data, statements, param); + nullBehaviorize(builderType, data, statements, param, md); if (returnStatement != null) statements.add(returnStatement); md.statements = statements.toArray(new Statement[0]); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index 859cce94..16ed2d44 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -316,7 +316,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs()); Argument param = new Argument(data.getPluralName(), 0, paramType, ClassFileConstants.AccFinal); - nullBehaviorize(builderType, data, statements, param); + nullBehaviorize(builderType, data, statements, param, md); if (returnStatement != null) statements.add(returnStatement); diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 53a518b4..b17e34d8 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -2096,15 +2096,7 @@ public class JavacHandlerUtil { * Returns {@code true} if the provided node supports static methods and types (top level or static class) */ public static boolean isStaticAllowed(JavacNode typeNode) { - boolean staticAllowed = true; - - while (typeNode.getKind() != Kind.COMPILATION_UNIT) { - if (!staticAllowed) return false; - - staticAllowed = typeNode.isStatic(); - typeNode = typeNode.up(); - } - return true; + return typeNode.isStatic() || typeNode.up() == null || typeNode.up().getKind() == Kind.COMPILATION_UNIT || isRecord(typeNode); } public static JavacNode upToTypeNode(JavacNode node) { diff --git a/src/eclipseAgent/lombok/eclipse/agent/MavenEcjBootstrapApp.java b/src/eclipseAgent/lombok/eclipse/agent/MavenEcjBootstrapApp.java new file mode 100644 index 00000000..7f9d4d36 --- /dev/null +++ b/src/eclipseAgent/lombok/eclipse/agent/MavenEcjBootstrapApp.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2022 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.eclipse.agent; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.List; + +import com.zwitserloot.cmdreader.CmdReader; +import com.zwitserloot.cmdreader.Description; +import com.zwitserloot.cmdreader.InvalidCommandLineException; +import com.zwitserloot.cmdreader.Shorthand; + +import lombok.core.LombokApp; +import lombok.spi.Provides; + +@Provides +public class MavenEcjBootstrapApp extends LombokApp { + @Override public String getAppName() { + return "createMavenECJBootstrap"; + } + + @Override public String getAppDescription() { + return "Creates .mvn/jvm.config and .mvn/lombok-bootstrap.jar for\n" + + "use with the ECJ compiler."; + } + + private static class CmdArgs { + @Shorthand("w") + @Description("Overwrite existing files. Defaults to false.") + boolean overwrite = false; + + @Shorthand("o") + @Description("The root of a Maven project. Defaults to the current working directory.") + String output; + + @Shorthand({"h", "?"}) + @Description("Shows this help text") + boolean help; + } + + @Override public int runApp(List<String> rawArgs) throws Exception { + CmdReader<CmdArgs> reader = CmdReader.of(CmdArgs.class); + CmdArgs args; + try { + args = reader.make(rawArgs.toArray(new String[0])); + } catch (InvalidCommandLineException e) { + printHelp(reader, e.getMessage(), System.err); + return 1; + } + + if (args.help) { + printHelp(reader, null, System.out); + return 0; + } + + return createBootstrap(args.output, args.overwrite); + } + + private int createBootstrap(String root, boolean overwrite) { + File mvn = new File(root, ".mvn"); + int result = 0; + if (result == 0) result = makeMvn(mvn); + if (result == 0) result = makeJvmConfig(mvn, overwrite); + if (result == 0) result = makeJar(mvn, overwrite); + return result; + } + + private int makeMvn(File mvn) { + int result = 0; + Exception err = null; + try { + if (!mvn.exists() && !mvn.mkdirs()) result = 1; + } catch (Exception e) { + result = 1; + err = e; + } + if (result != 0) { + System.err.println("Could not create " + mvn.getPath()); + if (err != null) err.printStackTrace(System.err); + } + return result; + } + + private int makeJvmConfig(File mvn, boolean overwrite) { + File jvmConfig = new File(mvn, "jvm.config"); + if (jvmConfig.exists() && !overwrite) { + System.err.println(canonical(jvmConfig) + " exists but '-w' not specified."); + return 1; + } + try { + FileWriter writer = new FileWriter(jvmConfig); + writer.write("-javaagent:.mvn/lombok-bootstrap.jar"); + writer.flush(); + writer.close(); + System.out.println("Successfully created: " + canonical(jvmConfig)); + return 0; + } catch (Exception e) { + System.err.println("Could not create: " + canonical(jvmConfig)); + e.printStackTrace(System.err); + return 1; + } + } + + private int makeJar(File mvn, boolean overwrite) { + File jar = new File(mvn, "lombok-bootstrap.jar"); + if (jar.exists() && !overwrite) { + System.err.println(canonical(jar) + " but '-w' not specified."); + return 1; + } + try { + InputStream input = MavenEcjBootstrapApp.class.getResourceAsStream("/lombok/launch/mavenEcjBootstrapAgent.jar"); + FileOutputStream output = new FileOutputStream(jar); + try { + byte[] buffer = new byte[4096]; + int length; + while ((length = input.read(buffer)) > 0) output.write(buffer, 0, length); + output.flush(); + output.close(); + System.out.println("Successfully created: " + canonical(jar)); + return 0; + } finally { + try { + output.close(); + } catch (Exception ignore) {} + } + } catch (Exception e) { + System.err.println("Could not create: " + canonical(jar)); + e.printStackTrace(System.err); + return 1; + } + } + + private static String canonical(File out) { + try { + return out.getCanonicalPath(); + } catch (Exception e) { + return out.getAbsolutePath(); + } + } + + private void printHelp(CmdReader<CmdArgs> reader, String message, PrintStream out) { + if (message != null) { + out.println(message); + out.println("----------------------------"); + } + out.println(reader.generateCommandLineHelp("java -jar lombok.jar createMavenECJBootstrap")); + } +} diff --git a/src/mavenEcjBootstrapAgent/lombok/launch/MavenEcjBootstrapAgent.java b/src/mavenEcjBootstrapAgent/lombok/launch/MavenEcjBootstrapAgent.java new file mode 100644 index 00000000..b36e591f --- /dev/null +++ b/src/mavenEcjBootstrapAgent/lombok/launch/MavenEcjBootstrapAgent.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 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.launch; + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.ProtectionDomain; +import java.util.jar.JarFile; + +/** + * This Java agent does not transform bytecode, but acts as a watcher that can + * figure out when it is appropriate to load Lombok itself within a Maven + * execution. + * + * It relies on several facts: + * <ul> + * <li>maven-compiler-plugin contains an {@code AbstractCompilerMojo} class that + * compiler instances extend. + * <li>Maven loaders are {@code ClassRealms}, which extend {@code URLClassLoader}. + * <li>Each plugin dependency in the <em>pom.xml </em>is represented as a file URL on the + * ClassRealm that points to the artifact. + * <li>URLs to Maven artifacts contain the group and artifact ids + * ({@code [...]/groupid/artifactid/ver/artifactid-ver.jar}). + * <li>The Lombok Java agent class is {@code lombok.launch.Agent}. + * </ul> + * Given all of the above, the transformer simply waits for {@code AbstractCompilerMojo} + * to be loaded, then uses the loader to find the path to the Lombok jar file, + * and finally loads the Lombok agent using reflection. + */ +public final class MavenEcjBootstrapAgent { + private static final String MAVEN_COMPILER_TRIGGER_CLASS = "org/apache/maven/plugin/compiler/AbstractCompilerMojo"; + private static final String LOMBOK_URL_IDENTIFIER = "/org/projectlombok/lombok/"; + private static final String LOMBOK_AGENT_CLASS = "lombok.launch.Agent"; + private static final byte[] NOT_TRANSFORMED = null; + + private MavenEcjBootstrapAgent() {} + + public static void premain(final String agentArgs, final Instrumentation instrumentation) { + instrumentation.addTransformer(new ClassFileTransformer() { + @Override public byte[] transform(final ClassLoader loader, final String className, final Class<?> cbr, final ProtectionDomain pd, final byte[] cfb) throws IllegalClassFormatException { + if (MAVEN_COMPILER_TRIGGER_CLASS.equals(className)) { + for (final URL url : ((URLClassLoader) loader).getURLs()) { + if (url.getPath().contains(LOMBOK_URL_IDENTIFIER)) { + try { + instrumentation.appendToSystemClassLoaderSearch(new JarFile(url.getPath())); + MavenEcjBootstrapAgent.class.getClassLoader().loadClass(LOMBOK_AGENT_CLASS).getDeclaredMethod("premain", String.class, Instrumentation.class).invoke(null, agentArgs, instrumentation); + instrumentation.removeTransformer(this); + break; + } catch (Exception e) { + // There are no appropriate loggers available at + // this point in time. + e.printStackTrace(System.err); + } + } + } + } + return NOT_TRANSFORMED; + } + }); + } +} diff --git a/test/transform/resource/after-delombok/LoggerFlogger.java b/test/transform/resource/after-delombok/LoggerFlogger.java index 41d49fe4..0fe8083a 100644 --- a/test/transform/resource/after-delombok/LoggerFlogger.java +++ b/test/transform/resource/after-delombok/LoggerFlogger.java @@ -12,3 +12,15 @@ class LoggerFloggerOuter { private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass(); } } +enum LoggerFloggerWithEnum { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass(); +} +class LoggerFloggerWithInnerEnum { + enum Inner { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass(); + } +} diff --git a/test/transform/resource/after-delombok/LoggerFloggerRecord.java b/test/transform/resource/after-delombok/LoggerFloggerRecord.java new file mode 100644 index 00000000..9cc0c9c0 --- /dev/null +++ b/test/transform/resource/after-delombok/LoggerFloggerRecord.java @@ -0,0 +1,6 @@ +class LoggerFloggerRecord { + record Inner(String x) { + @java.lang.SuppressWarnings("all") + private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass(); + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerJBossLog.java b/test/transform/resource/after-delombok/LoggerJBossLog.java index 5fd98aa6..1f2a240f 100644 --- a/test/transform/resource/after-delombok/LoggerJBossLog.java +++ b/test/transform/resource/after-delombok/LoggerJBossLog.java @@ -12,6 +12,18 @@ class LoggerJBossLogOuter { private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(Inner.class); } } +enum LoggerJBossLogWithEnum { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLogWithEnum.class); +} +class LoggerJBossLogWithInnerEnum { + enum Inner { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(Inner.class); + } +} class LoggerJBossLogWithDifferentLoggerName { @java.lang.SuppressWarnings("all") diff --git a/test/transform/resource/after-delombok/LoggerJul.java b/test/transform/resource/after-delombok/LoggerJul.java index cfb44fde..471e614c 100644 --- a/test/transform/resource/after-delombok/LoggerJul.java +++ b/test/transform/resource/after-delombok/LoggerJul.java @@ -14,4 +14,17 @@ class LoggerJulWithStaticField { @java.lang.SuppressWarnings("all") private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggerJulWithStaticField.TOPIC); static final String TOPIC = "StaticField"; +} +enum LoggerJulWithEnum { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggerJulWithEnum.class.getName()); +} +class LoggerJulWithInnerEnum { + + enum Inner { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(Inner.class.getName()); + } }
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerLog4j.java b/test/transform/resource/after-delombok/LoggerLog4j.java index cef83621..c07e14fa 100644 --- a/test/transform/resource/after-delombok/LoggerLog4j.java +++ b/test/transform/resource/after-delombok/LoggerLog4j.java @@ -15,3 +15,16 @@ class LoggerLog4jWithStaticField { private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LoggerLog4jWithStaticField.TOPIC); static final String TOPIC = "StaticField"; } +enum LoggerLog4jWithEnum { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LoggerLog4jWithEnum.class); +} +class LoggerLog4jWithInnerEnum { + + enum Inner { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(Inner.class); + } +} diff --git a/test/transform/resource/after-delombok/LoggerLog4j2.java b/test/transform/resource/after-delombok/LoggerLog4j2.java index cba516f2..5db281be 100644 --- a/test/transform/resource/after-delombok/LoggerLog4j2.java +++ b/test/transform/resource/after-delombok/LoggerLog4j2.java @@ -15,4 +15,17 @@ class LoggerLog4j2WithStaticField { @java.lang.SuppressWarnings("all") private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LoggerLog4j2WithStaticField.TOPIC); static final String TOPIC = "StaticField"; +} +enum LoggerLog4j2WithEnum { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LoggerLog4j2WithEnum.class); +} +class LoggerLog4j2WithInnerEnum { + + enum Inner { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(Inner.class); + } }
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerSlf4j.java b/test/transform/resource/after-delombok/LoggerSlf4j.java index 152c8708..099a65ad 100644 --- a/test/transform/resource/after-delombok/LoggerSlf4j.java +++ b/test/transform/resource/after-delombok/LoggerSlf4j.java @@ -6,6 +6,18 @@ class LoggerSlf4jWithImport { @java.lang.SuppressWarnings("all") private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerSlf4jWithImport.class); } +enum LoggerSlf4jWithEnum { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerSlf4jWithEnum.class); +} +class LoggerSlf4jWithInnerEnum { + enum Inner { + CONSTANT; + @java.lang.SuppressWarnings("all") + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Inner.class); + } +} class LoggerSlf4jOuter { static class Inner { @java.lang.SuppressWarnings("all") diff --git a/test/transform/resource/after-ecj/LoggerFlogger.java b/test/transform/resource/after-ecj/LoggerFlogger.java index d0526eee..b97082ff 100644 --- a/test/transform/resource/after-ecj/LoggerFlogger.java +++ b/test/transform/resource/after-ecj/LoggerFlogger.java @@ -28,3 +28,26 @@ class LoggerFloggerOuter { super(); } } +@Flogger enum LoggerFloggerWithEnum { + CONSTANT(), + private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass(); + <clinit>() { + } + LoggerFloggerWithEnum() { + super(); + } +} +class LoggerFloggerWithInnerEnum { + @Flogger enum Inner { + CONSTANT(), + private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass(); + <clinit>() { + } + Inner() { + super(); + } + } + LoggerFloggerWithInnerEnum() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/LoggerFloggerRecord.java b/test/transform/resource/after-ecj/LoggerFloggerRecord.java new file mode 100644 index 00000000..86004b67 --- /dev/null +++ b/test/transform/resource/after-ecj/LoggerFloggerRecord.java @@ -0,0 +1,16 @@ +import lombok.extern.flogger.Flogger; +class LoggerFloggerRecord { + static @Flogger record Inner(String x) { + private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass(); +/* Implicit */ private final String x; + <clinit>() { + } + public Inner(String x) { + super(); + .x = x; + } + } + LoggerFloggerRecord() { + super(); + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerJBossLog.java b/test/transform/resource/after-ecj/LoggerJBossLog.java index c47f6c9e..13d332a6 100644 --- a/test/transform/resource/after-ecj/LoggerJBossLog.java +++ b/test/transform/resource/after-ecj/LoggerJBossLog.java @@ -28,6 +28,29 @@ class LoggerJBossLogOuter { super(); } } +@JBossLog enum LoggerJBossLogWithEnum { + CONSTANT(), + private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLogWithEnum.class); + <clinit>() { + } + LoggerJBossLogWithEnum() { + super(); + } +} +class LoggerJBossLogWithInnerEnum { + @JBossLog enum Inner { + CONSTANT(), + private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(Inner.class); + <clinit>() { + } + Inner() { + super(); + } + } + LoggerJBossLogWithInnerEnum() { + super(); + } +} @JBossLog(topic = "DifferentLogger") class LoggerJBossLogWithDifferentLoggerName { private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger("DifferentLogger"); <clinit>() { diff --git a/test/transform/resource/after-ecj/LoggerJul.java b/test/transform/resource/after-ecj/LoggerJul.java index 20cc5407..d1408245 100644 --- a/test/transform/resource/after-ecj/LoggerJul.java +++ b/test/transform/resource/after-ecj/LoggerJul.java @@ -31,4 +31,27 @@ import lombok.extern.java.Log; LoggerJulWithStaticField() { super(); } +} +@Log enum LoggerJulWithEnum { + CONSTANT(), + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggerJulWithEnum.class.getName()); + <clinit>() { + } + LoggerJulWithEnum() { + super(); + } +} +class LoggerJulWithInnerEnum { + @Log enum Inner { + CONSTANT(), + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(Inner.class.getName()); + <clinit>() { + } + Inner() { + super(); + } + } + LoggerJulWithInnerEnum() { + super(); + } }
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerLog4j.java b/test/transform/resource/after-ecj/LoggerLog4j.java index e7d6c813..4d67b133 100644 --- a/test/transform/resource/after-ecj/LoggerLog4j.java +++ b/test/transform/resource/after-ecj/LoggerLog4j.java @@ -31,4 +31,27 @@ import lombok.extern.log4j.Log4j; LoggerLog4jWithStaticField() { super(); } +} +@Log4j enum LoggerLog4jWithEnum { + CONSTANT(), + private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LoggerLog4jWithEnum.class); + <clinit>() { + } + LoggerLog4jWithEnum() { + super(); + } +} +class LoggerLog4jWithInnerEnum { + @Log4j enum Inner { + CONSTANT(), + private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(Inner.class); + <clinit>() { + } + Inner() { + super(); + } + } + LoggerLog4jWithInnerEnum() { + super(); + } }
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerLog4j2.java b/test/transform/resource/after-ecj/LoggerLog4j2.java index 88def98d..72d4ff5f 100644 --- a/test/transform/resource/after-ecj/LoggerLog4j2.java +++ b/test/transform/resource/after-ecj/LoggerLog4j2.java @@ -31,4 +31,27 @@ import lombok.extern.log4j.Log4j2; LoggerLog4j2WithStaticField() { super(); } +} +@Log4j2 enum LoggerLog4j2WithEnum { + CONSTANT(), + private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LoggerLog4j2WithEnum.class); + <clinit>() { + } + LoggerLog4j2WithEnum() { + super(); + } +} +class LoggerLog4j2WithInnerEnum { + @Log4j2 enum Inner { + CONSTANT(), + private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(Inner.class); + <clinit>() { + } + Inner() { + super(); + } + } + LoggerLog4j2WithInnerEnum() { + super(); + } }
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerSlf4j.java b/test/transform/resource/after-ecj/LoggerSlf4j.java index 286d023b..85e49186 100644 --- a/test/transform/resource/after-ecj/LoggerSlf4j.java +++ b/test/transform/resource/after-ecj/LoggerSlf4j.java @@ -15,6 +15,29 @@ import lombok.extern.slf4j.Slf4j; super(); } } +@Slf4j enum LoggerSlf4jWithEnum { + CONSTANT(), + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerSlf4jWithEnum.class); + <clinit>() { + } + LoggerSlf4jWithEnum() { + super(); + } +} +class LoggerSlf4jWithInnerEnum { + @Slf4j enum Inner { + CONSTANT(), + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Inner.class); + <clinit>() { + } + Inner() { + super(); + } + } + LoggerSlf4jWithInnerEnum() { + super(); + } +} class LoggerSlf4jOuter { static @lombok.extern.slf4j.Slf4j class Inner { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Inner.class); diff --git a/test/transform/resource/before/LoggerFlogger.java b/test/transform/resource/before/LoggerFlogger.java index b143aae9..4bdc20b0 100644 --- a/test/transform/resource/before/LoggerFlogger.java +++ b/test/transform/resource/before/LoggerFlogger.java @@ -14,3 +14,15 @@ class LoggerFloggerOuter { } } + +@Flogger +enum LoggerFloggerWithEnum { + CONSTANT; +} + +class LoggerFloggerWithInnerEnum { + @Flogger + enum Inner { + CONSTANT; + } +} diff --git a/test/transform/resource/before/LoggerFloggerRecord.java b/test/transform/resource/before/LoggerFloggerRecord.java new file mode 100644 index 00000000..908704d6 --- /dev/null +++ b/test/transform/resource/before/LoggerFloggerRecord.java @@ -0,0 +1,8 @@ +// version 14: + +import lombok.extern.flogger.Flogger; + +class LoggerFloggerRecord { + @Flogger + record Inner(String x) {} +} diff --git a/test/transform/resource/before/LoggerJBossLog.java b/test/transform/resource/before/LoggerJBossLog.java index f3480867..a26a0f7b 100644 --- a/test/transform/resource/before/LoggerJBossLog.java +++ b/test/transform/resource/before/LoggerJBossLog.java @@ -15,6 +15,18 @@ class LoggerJBossLogOuter { } } +@JBossLog +enum LoggerJBossLogWithEnum { + CONSTANT; +} + +class LoggerJBossLogWithInnerEnum { + @JBossLog + enum Inner { + CONSTANT; + } +} + @JBossLog(topic="DifferentLogger") class LoggerJBossLogWithDifferentLoggerName { } diff --git a/test/transform/resource/before/LoggerJul.java b/test/transform/resource/before/LoggerJul.java index 7b10d015..24fcdcde 100644 --- a/test/transform/resource/before/LoggerJul.java +++ b/test/transform/resource/before/LoggerJul.java @@ -15,4 +15,16 @@ class LoggerJulWithDifferentName { @Log(topic=LoggerJulWithStaticField.TOPIC) class LoggerJulWithStaticField { static final String TOPIC = "StaticField"; +} + +@Log +enum LoggerJulWithEnum { + CONSTANT; +} + +class LoggerJulWithInnerEnum { + @Log + enum Inner { + CONSTANT; + } }
\ No newline at end of file diff --git a/test/transform/resource/before/LoggerLog4j.java b/test/transform/resource/before/LoggerLog4j.java index b7086a05..3be24d74 100644 --- a/test/transform/resource/before/LoggerLog4j.java +++ b/test/transform/resource/before/LoggerLog4j.java @@ -15,4 +15,16 @@ class LoggerLog4jWithDifferentName { @Log4j(topic=LoggerLog4jWithStaticField.TOPIC) class LoggerLog4jWithStaticField { static final String TOPIC = "StaticField"; +} + +@Log4j +enum LoggerLog4jWithEnum { + CONSTANT; +} + +class LoggerLog4jWithInnerEnum { + @Log4j + enum Inner { + CONSTANT; + } }
\ No newline at end of file diff --git a/test/transform/resource/before/LoggerLog4j2.java b/test/transform/resource/before/LoggerLog4j2.java index 1dd48d7a..bf717cb8 100644 --- a/test/transform/resource/before/LoggerLog4j2.java +++ b/test/transform/resource/before/LoggerLog4j2.java @@ -16,4 +16,16 @@ class LoggerLog4j2WithDifferentName { @Log4j2(topic=LoggerLog4j2WithStaticField.TOPIC) class LoggerLog4j2WithStaticField { static final String TOPIC = "StaticField"; +} + +@Log4j2 +enum LoggerLog4j2WithEnum { + CONSTANT; +} + +class LoggerLog4j2WithInnerEnum { + @Log4j2 + enum Inner { + CONSTANT; + } }
\ No newline at end of file diff --git a/test/transform/resource/before/LoggerSlf4j.java b/test/transform/resource/before/LoggerSlf4j.java index c59db4ee..f6310bf5 100644 --- a/test/transform/resource/before/LoggerSlf4j.java +++ b/test/transform/resource/before/LoggerSlf4j.java @@ -8,6 +8,18 @@ class LoggerSlf4j { class LoggerSlf4jWithImport { } +@Slf4j +enum LoggerSlf4jWithEnum { + CONSTANT; +} + +class LoggerSlf4jWithInnerEnum { + @Slf4j + enum Inner { + CONSTANT; + } +} + class LoggerSlf4jOuter { @lombok.extern.slf4j.Slf4j static class Inner { diff --git a/test/transform/resource/messages-delombok/LoggerSlf4jOnNonType.java.messages b/test/transform/resource/messages-delombok/LoggerSlf4jOnNonType.java.messages index ca4d607f..b172ef79 100644 --- a/test/transform/resource/messages-delombok/LoggerSlf4jOnNonType.java.messages +++ b/test/transform/resource/messages-delombok/LoggerSlf4jOnNonType.java.messages @@ -1 +1 @@ -3 @Log is legal only on types. |||| 3 annotation type not applicable to this kind of declaration
\ No newline at end of file +3 @Log is legal only on types. |||| 3 annotation type not applicable to this kind of declaration |||| 3 annotation interface not applicable to this kind of declaration
\ No newline at end of file diff --git a/website/templates/features/ToString.html b/website/templates/features/ToString.html index 87e06649..c740ec81 100644 --- a/website/templates/features/ToString.html +++ b/website/templates/features/ToString.html @@ -3,7 +3,7 @@ <@f.scaffold title="@ToString" logline="No need to start a debugger to see your fields: Just let lombok generate a <code>toString</code> for you!"> <@f.overview> <p> - Any class definition may be annotated with <code>@ToString</code> to let lombok generate an implementation of the <code>toString()</code> method. By default, it'll print your class name, along with each field, in order, separated by commas. + Annotating a class with <code>@ToString</code> will cause lombok to generate an implementation of the <code>toString()</code> method. You use configuration options to specify whether field names should be included but otherwise the format is fixed: the class name followed by parentheses containing fields separated by commas, e.g. <code>MyClass(foo=123, bar=234)</code>. </p><p> By setting the <code>includeFieldNames</code> parameter to <em>true</em> you can add some clarity (but also quite some length) to the output of the <code>toString()</code> method. </p><p> diff --git a/website/templates/features/experimental/FieldNameConstants.html b/website/templates/features/experimental/FieldNameConstants.html index 06fa23b5..cc147d51 100644 --- a/website/templates/features/experimental/FieldNameConstants.html +++ b/website/templates/features/experimental/FieldNameConstants.html @@ -58,6 +58,8 @@ Any parameters of lombok annotations that take strings need to be supplied actual string literals; you cannot have references to constants like those generated by <code>@FieldNameConstants</code>. If you'd like to use <code>@FieldNameConstants</code> to for example fill in the <code>of</code> and/or <code>exclude</code> parameters of <code>@ToString</code> and similar lombok annotations, use the <code>@ToString.Include</code> / <code>@ToString.Exclude</code> etc system instead; these are described at the feature pages for those features. </p><p> Like other lombok handlers that touch fields, any field whose name starts with a dollar (<code>$</code>) symbol is skipped entirely. Such a field will not be modified at all. Static fields are also skipped. + </p><p> + <em>MapStruct interop:</em> When making references to field name constants inside MapStruct's <code>@Mapping</code>, and you use that annotation more than once on a node, you must manually wrap these in the <code>@Mappings</code> 'container annotation'. Like so: <code>@Mappings({@Mapping(target = Entity.Fields.entityProperty, source = "dtoProperty")})</code>. </p> </@f.smallPrint> </@f.scaffold> diff --git a/website/templates/features/experimental/UtilityClass.html b/website/templates/features/experimental/UtilityClass.html index c5f51e29..915fe5c9 100644 --- a/website/templates/features/experimental/UtilityClass.html +++ b/website/templates/features/experimental/UtilityClass.html @@ -11,9 +11,11 @@ <ul> <li> Some debate as to whether its common enough to count as boilerplate. + </li><li> + Due to limitations in javac, currently non-star static imports <em>cannot</em> be used to import stuff from <code>@UtilityClass</code>es; don't static import, or use star imports. </li> </ul> - Current status: <em>positive</em> - Currently we feel this feature may move out of experimental status with no or minor changes soon. + Current status: <em>negative</em> - Currently we feel this feature cannot move out of experimental status due to fundamental issues with non-star static imports. </@f.experimental> <@f.overview> diff --git a/website/templates/setup/ecj-in-maven-pom-example.xml b/website/templates/setup/ecj-in-maven-pom-example.xml deleted file mode 100644 index 3bb10722..00000000 --- a/website/templates/setup/ecj-in-maven-pom-example.xml +++ /dev/null @@ -1,81 +0,0 @@ -<#noparse> -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <groupId>org.projectlombok</groupId> - <artifactId>eclipse-compiler-test</artifactId> - <version>1.0-SNAPSHOT</version> - - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> -</#noparse> - <lombok.version>${version}</lombok.version> -<#noparse> - </properties> - - <dependencies> - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - <scope>provided</scope> - </dependency> - </dependencies> - - <build> - <pluginManagement> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.1</version> - <configuration> - <compilerId>eclipse</compilerId> - <release>11</release> - </configuration> - <dependencies> - <dependency> - <groupId>org.codehaus.plexus</groupId> - <artifactId>plexus-compiler-eclipse</artifactId> - <version>2.8.6</version> - </dependency> - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - </dependency> - </dependencies> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <version>3.1.1</version> - <executions> - <execution> - <id>get-lombok</id> - <goals> - <goal>copy</goal> - </goals> - <configuration> - <artifactItems> - <artifactItem> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - <type>jar</type> - <outputDirectory>${project.build.directory}</outputDirectory> - <destFileName>lombok.jar</destFileName> - </artifactItem> - </artifactItems> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </pluginManagement> - </build> -</project> -</#noparse> diff --git a/website/templates/setup/ecj.html b/website/templates/setup/ecj.html index e01bc653..d888938a 100644 --- a/website/templates/setup/ecj.html +++ b/website/templates/setup/ecj.html @@ -1,32 +1,81 @@ <#import "_setup.html" as s> -<@s.scaffold title="ecj"> +<@s.scaffold title="ECJ"> <@s.introduction> <p> - ecj (the eclipse standalone compiler) is compatible with lombok. Use the following command line to enable lombok with ecj: + ECJ (the Eclipse standalone compiler) is compatible with Lombok. Use the following command line to enable Lombok with ECJ: <pre>java <strong>-javaagent:lombok.jar=ECJ</strong> -jar ecj.jar -cp lombok.jar -source 1.8 <em class="note">(rest of arguments)</em></pre> </p><p> - You may have to add the following VM argument, if you're using an older version of lombok or java: + You may have to add the following VM argument, if you're using an older version of Lombok or Java: <pre><strong>-Xbootclasspath/p:lombok.jar</strong></pre> </p><p> - If you're using a tool based on ecj, adding these VM arguments and adding lombok.jar to the classpath should work. + If you're using a tool based on ECJ, adding these VM arguments and adding <code>lombok.jar</code> to the classpath should work. </p> </@s.introduction> - + <@s.section title="Maven"> <p> - It is possible to <a href="/setup/ecj-in-maven-pom-example.xml">configure</a> <code>maven-compiler-plugin</code> with <code>maven-dependency-plugin</code> and <code>plexus-compiler-eclipse</code>. + Lombok comes with a tiny bootstrap agent that can be included in your project to allow ECJ to easily work with Maven. + To create this agent, run: + <pre>java -jar lombok.jar createMavenECJBootstrap -o <em class="note">/path/to/project/root</em></pre> + </p><p> + The -o path should contain your <code>pom.xml</code>. </p><p> - Before the <code>compile</code> phase, you will have to set your <code>MAVEN_OPTS</code> environment variable to include the <code>javaagent</code> argument. In the example below, <code>target</code> is your <code>${r"${project.build.directory}"}</code>. + This will create two files, <code>.mvn/jvm.config</code> and <code>.mvn/lombok-bootstrap.jar</code>. Maven will use these files + to activate the standard Lombok Java agent at the right time. These can be committed in source control for a portable build. </p><p> - Use the following commands in sequence to enable lombok with ecj in your Maven build: -<pre> -# Make sure you've updated your pom as per <a href="/setup/ecj-in-maven-pom-example.xml">this example</a>. -mvn clean <strong>dependency:copy@get-lombok</strong> -set MAVEN_OPTS=<strong>-javaagent:target/lombok.jar=ECJ</strong> <em class="note">(or your OS's equivalent)</em> -mvn install -set MAVEN_OPTS= <em class="note">(or your OS's equivalent)</em> + You must also update your <code>pom.xml</code> to add Lombok as a dependency to the <code>maven-compiler-plugin</code>. A minimal example follows:<pre> +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.projectlombok</groupId> + <artifactId>eclipse-compiler-test</artifactId> + <version>1.0-SNAPSHOT</version> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <lombok.version>${version}</lombok.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.10.1</version> + <configuration> + <compilerId>eclipse</compilerId> + </configuration> + <dependencies> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-compiler-eclipse</artifactId> + <version>2.11.1</version> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </pluginManagement> + </build> +</project> </pre> - </p> +</p> </@s.section> </@s.scaffold> diff --git a/website/templates/setup/maven.html b/website/templates/setup/maven.html index 0e28421f..f6c36822 100644 --- a/website/templates/setup/maven.html +++ b/website/templates/setup/maven.html @@ -37,6 +37,12 @@ </pre> </p> </@s.section> + + <@s.section title="Eclipse Compiler (ECJ/JDT)"> + <p> + Check out the instructions on <a href="/setup/ecj">the ECJ page</a>. + </p> + </@s.section> <@s.section title="Delomboking: The Lombok Maven Plugin"> <p> |