diff options
| author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2022-02-08 06:02:05 +0100 |
|---|---|---|
| committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2022-02-08 06:02:05 +0100 |
| commit | 261758b4448b3d48ff2f48926ffcb8ea66121603 (patch) | |
| tree | 1996f090ab62b3626fe875406a294e724ad94a12 | |
| parent | 8a914b1bf0eaa13178e719431add47b78d4e7277 (diff) | |
| download | lombok-261758b4448b3d48ff2f48926ffcb8ea66121603.tar.gz lombok-261758b4448b3d48ff2f48926ffcb8ea66121603.tar.bz2 lombok-261758b4448b3d48ff2f48926ffcb8ea66121603.zip | |
[implements #1456] accessors can now be made final via `@Accessors`.
34 files changed, 527 insertions, 71 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 9c22025d..0ba93306 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -5,6 +5,7 @@ Lombok Changelog * 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) * 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) diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 457246e7..22d5a4c5 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 The Project Lombok Authors. + * Copyright (C) 2013-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 @@ -550,7 +550,7 @@ public class ConfigurationKeys { * * For any class without an {@code @Accessors} that explicitly defines the {@code prefix} option, this list of prefixes is used. */ - public static final ConfigurationKey<List<String>> ACCESSORS_PREFIX = new ConfigurationKey<List<String>>("lombok.accessors.prefix", "Strip this field prefix, like 'f' or 'm_', from the names of generated getters and setters.") {}; + public static final ConfigurationKey<List<String>> ACCESSORS_PREFIX = new ConfigurationKey<List<String>>("lombok.accessors.prefix", "Strip this field prefix, like 'f' or 'm_', from the names of generated getters, setters, and with-ers.") {}; /** * lombok configuration: {@code lombok.accessors.chain} = {@code true} | {@code false}. @@ -567,6 +567,13 @@ public class ConfigurationKeys { public static final ConfigurationKey<Boolean> ACCESSORS_FLUENT = new ConfigurationKey<Boolean>("lombok.accessors.fluent", "Generate getters and setters using only the field name (no get/set prefix) (default: false).") {}; /** + * lombok configuration: {@code lombok.accessors.makeFinal} = {@code true} | {@code false}. + * + * Unless an explicit {@code @Accessors} that explicitly defines the {@code makeFinal} option, this value is used (default = false). + */ + public static final ConfigurationKey<Boolean> ACCESSORS_MAKE_FINAL = new ConfigurationKey<Boolean>("lombok.accessors.makeFinal", "Generate getters, setters and with-ers with the 'final' modifier (default: false).") {}; + + /** * lombok configuration: {@code lombok.accessors.capitalization} = {@code basic} | {@code beanspec}. * * 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. diff --git a/src/core/lombok/core/AnnotationValues.java b/src/core/lombok/core/AnnotationValues.java index f5db553c..390e9b71 100644 --- a/src/core/lombok/core/AnnotationValues.java +++ b/src/core/lombok/core/AnnotationValues.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2013 The Project Lombok Authors. + * Copyright (C) 2009-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 @@ -550,4 +550,25 @@ public class AnnotationValues<A extends Annotation> { result.append(typeName); return result.toString(); } + + /** + * Creates an amalgamation where any values in this AnnotationValues that aren't explicit are 'enriched' by explicitly set stuff from {@code defaults}. + * Note that this code may modify self and then returns self, or it returns defaults - do not rely on immutability nor on getting self. + */ + public AnnotationValues<A> integrate(AnnotationValues<A> defaults) { + if (values.isEmpty()) return defaults; + for (Map.Entry<String, AnnotationValue> entry : defaults.values.entrySet()) { + if (!entry.getValue().isExplicit) continue; + AnnotationValue existingValue = values.get(entry.getKey()); + if (existingValue != null && existingValue.isExplicit) continue; + values.put(entry.getKey(), entry.getValue()); + } + return this; + } + + /** Returns {@code true} if the annotation has zero parameters. */ + public boolean isMarking() { + for (AnnotationValue v : values.values()) if (v.isExplicit) return false; + return true; + } } diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 2415b750..039ce870 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 The Project Lombok Authors. + * Copyright (C) 2013-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 @@ -555,6 +555,14 @@ public class HandlerUtil { return chain || fluent; } + public static boolean shouldMakeFinal0(AnnotationValues<Accessors> accessors, AST<?, ?, ?> ast) { + boolean isExplicit = accessors.isExplicit("makeFinal"); + if (isExplicit) return accessors.getAsBoolean("makeFinal"); + Boolean config = ast.readConfiguration(ConfigurationKeys.ACCESSORS_MAKE_FINAL); + if (config != null) return config.booleanValue(); + return false; + } + @SuppressWarnings({"all", "unchecked", "deprecation"}) public static final List<String> INVALID_ON_BUILDERS = Collections.unmodifiableList( Arrays.<String>asList( diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 6483a749..65e2c5c8 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2021 The Project Lombok Authors. + * Copyright (C) 2009-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 @@ -1632,6 +1632,14 @@ public class EclipseHandlerUtil { } /** + * Translates the given field into all possible getter names. + * Convenient wrapper around {@link HandlerUtil#toAllGetterNames(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static List<String> toAllGetterNames(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toAllGetterNames(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** * @return the likely getter name for the stated field. (e.g. private boolean foo; to isFoo). * * Convenient wrapper around {@link HandlerUtil#toGetterName(lombok.core.AnnotationValues, CharSequence, boolean)}. @@ -1641,6 +1649,15 @@ public class EclipseHandlerUtil { } /** + * @return the likely getter name for the stated field. (e.g. private boolean foo; to isFoo). + * + * Convenient wrapper around {@link HandlerUtil#toGetterName(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static String toGetterName(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toGetterName(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** * Translates the given field into all possible setter names. * Convenient wrapper around {@link HandlerUtil#toAllSetterNames(lombok.core.AnnotationValues, CharSequence, boolean)}. */ @@ -1649,6 +1666,14 @@ public class EclipseHandlerUtil { } /** + * Translates the given field into all possible setter names. + * Convenient wrapper around {@link HandlerUtil#toAllSetterNames(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static java.util.List<String> toAllSetterNames(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toAllSetterNames(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** * @return the likely setter name for the stated field. (e.g. private boolean foo; to setFoo). * * Convenient wrapper around {@link HandlerUtil#toSetterName(lombok.core.AnnotationValues, CharSequence, boolean)}. @@ -1658,6 +1683,15 @@ public class EclipseHandlerUtil { } /** + * @return the likely setter name for the stated field. (e.g. private boolean foo; to setFoo). + * + * Convenient wrapper around {@link HandlerUtil#toSetterName(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static String toSetterName(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toSetterName(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** * Translates the given field into all possible with names. * Convenient wrapper around {@link HandlerUtil#toAllWithNames(lombok.core.AnnotationValues, CharSequence, boolean)}. */ @@ -1666,6 +1700,14 @@ public class EclipseHandlerUtil { } /** + * Translates the given field into all possible with names. + * Convenient wrapper around {@link HandlerUtil#toAllWithNames(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static java.util.List<String> toAllWithNames(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toAllWithNames(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** * Translates the given field into all possible withBy names. * Convenient wrapper around {@link HandlerUtil#toAllWithByNames(lombok.core.AnnotationValues, CharSequence, boolean)}. */ @@ -1674,6 +1716,14 @@ public class EclipseHandlerUtil { } /** + * Translates the given field into all possible withBy names. + * Convenient wrapper around {@link HandlerUtil#toAllWithByNames(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static java.util.List<String> toAllWithByNames(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toAllWithByNames(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** * @return the likely with name for the stated field. (e.g. private boolean foo; to withFoo). * * Convenient wrapper around {@link HandlerUtil#toWithName(lombok.core.AnnotationValues, CharSequence, boolean)}. @@ -1683,6 +1733,15 @@ public class EclipseHandlerUtil { } /** + * @return the likely with name for the stated field. (e.g. private boolean foo; to withFoo). + * + * Convenient wrapper around {@link HandlerUtil#toWithName(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static String toWithName(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toWithName(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** * @return the likely withBy name for the stated field. (e.g. private boolean foo; to withFooBy). * * Convenient wrapper around {@link HandlerUtil#toWithByName(lombok.core.AnnotationValues, CharSequence, boolean)}. @@ -1692,12 +1751,27 @@ public class EclipseHandlerUtil { } /** + * @return the likely withBy name for the stated field. (e.g. private boolean foo; to withFooBy). + * + * Convenient wrapper around {@link HandlerUtil#toWithByName(lombok.core.AnnotationValues, CharSequence, boolean)}. + */ + public static String toWithByName(EclipseNode field, boolean isBoolean, AnnotationValues<Accessors> accessors) { + return HandlerUtil.toWithByName(field.getAst(), accessors, field.getName(), isBoolean); + } + + /** + * When generating a setter/getter/wither, should it be made final? + */ + public static boolean shouldMakeFinal(EclipseNode field, AnnotationValues<Accessors> accessors) { + if ((((FieldDeclaration) field.get()).modifiers & ClassFileConstants.AccStatic) != 0) return false; + return shouldMakeFinal0(accessors, field.getAst()); + } + /** * When generating a setter, the setter either returns void (beanspec) or Self (fluent). * This method scans for the {@code Accessors} annotation and associated config properties to figure that out. */ - public static boolean shouldReturnThis(EclipseNode field) { + public static boolean shouldReturnThis(EclipseNode field, AnnotationValues<Accessors> accessors) { if ((((FieldDeclaration) field.get()).modifiers & ClassFileConstants.AccStatic) != 0) return false; - AnnotationValues<Accessors> accessors = EclipseHandlerUtil.getAccessorsForField(field); return shouldReturnThis0(accessors, field.getAst()); } @@ -1760,9 +1834,12 @@ public class EclipseHandlerUtil { } public static AnnotationValues<Accessors> getAccessorsForField(EclipseNode field) { + AnnotationValues<Accessors> values = null; + for (EclipseNode node : field.down()) { if (annotationTypeMatches(Accessors.class, node)) { - return createAnnotation(Accessors.class, node); + values = createAnnotation(Accessors.class, node); + break; } } @@ -1770,15 +1847,16 @@ public class EclipseHandlerUtil { while (current != null) { for (EclipseNode node : current.down()) { if (annotationTypeMatches(Accessors.class, node)) { - return createAnnotation(Accessors.class, node); + AnnotationValues<Accessors> onType = createAnnotation(Accessors.class, node); + values = values == null ? onType : values.integrate(onType); } } current = current.up(); } - return AnnotationValues.of(Accessors.class, field); + return values == null ? AnnotationValues.of(Accessors.class, field) : values; } - + public static EclipseNode upToTypeNode(EclipseNode node) { if (node == null) throw new NullPointerException("node"); while (node != null && !(node.get() instanceof TypeDeclaration)) node = node.up(); @@ -2823,7 +2901,7 @@ public class EclipseHandlerUtil { if (!sectionBased) { out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), JavadocTag.RETURN); } - return shouldReturnThis(node) ? addReturnsThisIfNeeded(out) : out; + return shouldReturnThis(node, EclipseHandlerUtil.getAccessorsForField(node)) ? addReturnsThisIfNeeded(out) : out; } } diff --git a/src/core/lombok/eclipse/handlers/HandleAccessors.java b/src/core/lombok/eclipse/handlers/HandleAccessors.java index 6a92dee2..3bb63aa6 100644 --- a/src/core/lombok/eclipse/handlers/HandleAccessors.java +++ b/src/core/lombok/eclipse/handlers/HandleAccessors.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2021 The Project Lombok Authors. + * Copyright (C) 2014-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 @@ -39,5 +39,6 @@ public class HandleAccessors extends EclipseAnnotationHandler<Accessors> { // Accessors itself is handled by HandleGetter/Setter; this is just to ensure that usages are flagged if requested. handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.ACCESSORS_FLAG_USAGE, "@Accessors"); + if (annotation.isMarking()) annotationNode.addWarning("Accessors on its own does nothing. Set at least one parameter"); } } diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 7f8fdef2..31236d21 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2021 The Project Lombok Authors. + * Copyright (C) 2009-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 @@ import java.util.Map; import lombok.AccessLevel; import lombok.ConfigurationKeys; +import lombok.experimental.Accessors; import lombok.experimental.Delegate; import lombok.spi.Provides; import lombok.Getter; @@ -190,7 +191,8 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { TypeReference fieldType = copyType(field.type, source); boolean isBoolean = isBoolean(fieldType); - String getterName = toGetterName(fieldNode, isBoolean); + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); + String getterName = toGetterName(fieldNode, isBoolean, accessors); if (getterName == null) { errorNode.addWarning("Not generating getter for this field: It does not fit your @Accessors prefix list."); @@ -199,7 +201,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { int modifier = toEclipseModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); - for (String altName : toAllGetterNames(fieldNode, isBoolean)) { + for (String altName : toAllGetterNames(fieldNode, isBoolean, accessors)) { switch (methodExists(altName, fieldNode, false, 0)) { case EXISTS_BY_LOMBOK: return; @@ -247,7 +249,9 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { statements = createSimpleGetterBody(source, fieldNode); } + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); MethodDeclaration method = new MethodDeclaration(parent.compilationResult); + if (shouldMakeFinal(fieldNode, accessors)) modifier |= ClassFileConstants.AccFinal; method.modifiers = modifier; method.returnType = returnType; method.annotations = null; diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 0fdd058f..fda1651d 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2021 The Project Lombok Authors. + * Copyright (C) 2009-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 @@ -37,6 +37,7 @@ import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.experimental.Accessors; import lombok.spi.Provides; import org.eclipse.jdt.internal.compiler.ast.ASTNode; @@ -150,8 +151,9 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); TypeReference fieldType = copyType(field.type, source); boolean isBoolean = isBoolean(fieldType); - String setterName = toSetterName(fieldNode, isBoolean); - boolean shouldReturnThis = shouldReturnThis(fieldNode); + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); + String setterName = toSetterName(fieldNode, isBoolean, accessors); + boolean shouldReturnThis = shouldReturnThis(fieldNode, accessors); if (setterName == null) { fieldNode.addWarning("Not generating setter for this field: It does not fit your @Accessors prefix list."); @@ -160,7 +162,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { int modifier = toEclipseModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); - for (String altName : toAllSetterNames(fieldNode, isBoolean)) { + for (String altName : toAllSetterNames(fieldNode, isBoolean, accessors)) { switch (methodExists(altName, fieldNode, false, 1)) { case EXISTS_BY_LOMBOK: return; @@ -206,6 +208,8 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; MethodDeclaration method = new MethodDeclaration(parent.compilationResult); + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); + if (shouldMakeFinal(fieldNode, accessors)) modifier |= ClassFileConstants.AccFinal; method.modifiers = modifier; if (returnType != null) { method.returnType = returnType; diff --git a/src/core/lombok/eclipse/handlers/HandleWith.java b/src/core/lombok/eclipse/handlers/HandleWith.java index bfad682b..153f0c4a 100644 --- a/src/core/lombok/eclipse/handlers/HandleWith.java +++ b/src/core/lombok/eclipse/handlers/HandleWith.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2021 The Project Lombok Authors. + * Copyright (C) 2012-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 @@ -38,6 +38,7 @@ import lombok.core.configuration.CheckerFrameworkVersion; import lombok.core.AnnotationValues; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.experimental.Accessors; import lombok.spi.Provides; import org.eclipse.jdt.internal.compiler.ast.ASTNode; @@ -169,7 +170,8 @@ public class HandleWith extends EclipseAnnotationHandler<With> { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); TypeReference fieldType = copyType(field.type, source); boolean isBoolean = isBoolean(fieldType); - String withName = toWithName(fieldNode, isBoolean); + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); + String withName = toWithName(fieldNode, isBoolean, accessors); if (withName == null) { fieldNode.addWarning("Not generating a with method for this field: It does not fit your @Accessors prefix list."); @@ -191,7 +193,7 @@ public class HandleWith extends EclipseAnnotationHandler<With> { return; } - for (String altName : toAllWithNames(fieldNode, isBoolean)) { + for (String altName : toAllWithNames(fieldNode, isBoolean, accessors)) { switch (methodExists(altName, fieldNode, false, 1)) { case EXISTS_BY_LOMBOK: return; @@ -222,7 +224,9 @@ public class HandleWith extends EclipseAnnotationHandler<With> { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; MethodDeclaration method = new MethodDeclaration(parent.compilationResult); - if (makeAbstract) modifier = modifier | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody; + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); + if (makeAbstract) modifier |= ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody; + if (shouldMakeFinal(fieldNode, accessors)) modifier |= ClassFileConstants.AccFinal; method.modifiers = modifier; method.returnType = cloneSelfType(fieldNode, source); if (method.returnType == null) return null; diff --git a/src/core/lombok/eclipse/handlers/HandleWithBy.java b/src/core/lombok/eclipse/handlers/HandleWithBy.java index a8d13a84..5ab3cf81 100644 --- a/src/core/lombok/eclipse/handlers/HandleWithBy.java +++ b/src/core/lombok/eclipse/handlers/HandleWithBy.java @@ -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 @@ -61,6 +61,7 @@ import lombok.core.handlers.HandlerUtil.FieldAccess; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.experimental.Accessors; import lombok.experimental.WithBy; import lombok.spi.Provides; @@ -169,7 +170,8 @@ public class HandleWithBy extends EclipseAnnotationHandler<WithBy> { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); TypeReference fieldType = copyType(field.type, source); boolean isBoolean = isBoolean(fieldType); - String withName = toWithByName(fieldNode, isBoolean); + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); + String withName = toWithByName(fieldNode, isBoolean, accessors); if (withName == null) { fieldNode.addWarning("Not generating a withXBy method for this field: It does not fit your @Accessors prefix list."); @@ -191,7 +193,7 @@ public class HandleWithBy extends EclipseAnnotationHandler<WithBy> { return; } - for (String altName : toAllWithByNames(fieldNode, isBoolean)) { + for (String altName : toAllWithByNames(fieldNode, isBoolean, accessors)) { switch (methodExists(altName, fieldNode, false, 1)) { case EXISTS_BY_LOMBOK: return; @@ -242,7 +244,9 @@ public class HandleWithBy extends EclipseAnnotationHandler<WithBy> { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; MethodDeclaration method = new MethodDeclaration(parent.compilationResult); - if (makeAbstract) modifier = modifier | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody; + AnnotationValues<Accessors> accessors = getAccessorsForField(fieldNode); + if (makeAbstract) modifier |= ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody; + if (shouldMakeFinal(fieldNode, accessors)) modifier |= ClassFileConstants.AccFinal; method.modifiers = modifier; method.returnType = cloneSelfType(fieldNode, source); if (method.returnType == null) return null; diff --git a/src/core/lombok/experimental/Accessors.java b/src/core/lombok/experimental/Accessors.java index dc9ae4b0..394fe5c4 100644 --- a/src/core/lombok/experimental/Accessors.java +++ b/src/core/lombok/experimental/Accessors.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2017 The Project Lombok Authors. + * Copyright (C) 2012-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 @@ -27,11 +27,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * A container for settings for the generation of getters and setters. + * A container for settings for the generation of getters, setters and "with"-ers. * <p> * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Accessors">the project lombok features page for @Accessors</a>. * <p> - * Using this annotation does nothing by itself; an annotation that makes lombok generate getters and setters, + * Using this annotation does nothing by itself; an annotation that makes lombok generate getters, setters, or "with"-ers * such as {@link lombok.Setter} or {@link lombok.Data} is also required. */ @Target({ElementType.TYPE, ElementType.FIELD}) @@ -39,7 +39,8 @@ import java.lang.annotation.Target; public @interface Accessors { /** * If true, accessors will be named after the field and not include a {@code get} or {@code set} - * prefix. If true and {@code chain} is omitted, {@code chain} defaults to {@code true}. |
