diff --git a/AUTHORS b/AUTHORS index 547246d989..9281c9a9b1 100755 --- a/AUTHORS +++ b/AUTHORS @@ -49,6 +49,7 @@ Takuya Murakami Thomas Darimont Till Brychcy Victor Williams Stafusa da Silva +Yonatan Sherwin Yun Zhi Lin By adding your name to this list, you grant full and irrevocable copyright and patent indemnity to Project Lombok and all use of Project Lombok in relation to all commits you add to Project Lombok, and you certify that you have the right to do so. diff --git a/buildScripts/tests.ant.xml b/buildScripts/tests.ant.xml index 9d9e9541df..838ac3534d 100644 --- a/buildScripts/tests.ant.xml +++ b/buildScripts/tests.ant.xml @@ -152,13 +152,18 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn + - Running TestEclipse on eclipse-@{version} on JVM${ant.java.version}. + + + + Running TestEclipse on eclipse-@{version} on JVM${ant.java.version} using. Compiler compliance level: @{compiler.compliance.level} + @@ -175,11 +180,16 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn - + + + + + + @@ -217,5 +227,5 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn - + diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 583736f121..5c13e2e286 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -1,8 +1,17 @@ Lombok Changelog ---------------- -### v1.18.21 "Edgy Guinea Pig" -* Added the `@StandardException` feature. [Pull Request #2702](https://github.com/projectlombok/lombok/pull/2702). +### v1.18.24 "Edgy Guinea Pig" +* 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__! +* 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) + +### v1.18.22 (October 6th, 2021) +* PLATFORM: JDK17 support added. [Issue #2898](https://github.com/projectlombok/lombok/issues/2898). +* FEATURE: Added the `@StandardException` feature. [Pull Request #2702](https://github.com/projectlombok/lombok/pull/2702). +* IMPROBABLE BREAKING CHANGE: If the underlying compiler and `--release` / `--source` option is 10 or higher, lombok's `val` is now replaced by `final var`. That means compound declarations such as `val x = 10, y = 12;` now fail (lombok's old `val` implementation supported it, javac's `var` does not), but IDE support in particular is more reliable. We decided it was worth the tradeoff. +* BUGFIX: Syntax highlighting in VSCode now works reliably when using lombok. [Issue #2950](https://github.com/projectlombok/lombok/issues/2950). +* BUGFIX: Eclipse's _organize imports_ feature would sometimes remove your `lombok.val` import. [Issue #2972](https://github.com/projectlombok/lombok/issues/2972). + ### v1.18.20 (April 2nd, 2021) * PLATFORM: JDK16 support added. [Issue #2681](https://github.com/projectlombok/lombok/issues/2681). diff --git a/doc/debug-insights/eclipse.txt b/doc/debug-insights/eclipse.txt new file mode 100644 index 0000000000..b653594a01 --- /dev/null +++ b/doc/debug-insights/eclipse.txt @@ -0,0 +1,22 @@ +# How to debug lombok running in eclipse + +## Overview + +Lombok's build scripting can generate a target for you, that lets you run the same eclipse installation inside eclipse, in debug mode. Now you can add breakpoints. + +As lombok is an agent, lombok __must__ load from a jar file. +Nevertheless, lombok can be hot-code-replaced in the debugger. +This works via the loader: The lombok agent has its own classloading architecture, and this architecture is capable of loading lombok's class files from a location of your choosing. Choose the /bin dir from your eclipse project which will help with debugging; eclipse will then be able to apply HCR to the eclipse-running-in-eclipse. Unless there are issues with the loader architecture itself, of course. + +The end goal is that you can make some changes to the lombok sources in your eclipse, then click the 'debug' button, and a new 'test eclipse' starts up using lombok as you wrote it just now. You can now make changes to lombok sources in the original eclipse, hit 'save', and these changes now get automatically applied to the 'test eclipse', as long as you aren't making any changes to signatures (add or remove methods/fields/types, or change return types, param types, etc). + +If you have the sources to eclipse itself, you can open them, set breakpoints, and step through, though be aware that lombok's agent injection system does cause some issues here; we move methods into different classes and eclipse's debugger naturally doesn't understand this, so you can't breakpoint lombok's own patch methods, and stepping through them 'works' but looks bizarre in the debugger as the debugger now thinks your source file clearly cannot possibly match the class file currently running. Just keep going ('step out'), eclipse will figure it out again once you're back in un-instrumented eclipse code. + + +TODO: + +Describe in detail: + +* Which ant tasks to run to create the targets +* How to modify this target, if needed, to point at your bin dir + diff --git a/doc/debug-insights/vscode.txt b/doc/debug-insights/vscode.txt new file mode 100644 index 0000000000..efc5561992 --- /dev/null +++ b/doc/debug-insights/vscode.txt @@ -0,0 +1,7 @@ +As per @Rawi01's experimenting: + +* VSCode's lombok plugin simply adds the appropriate `-javaagent` options when it fires up the eclipse-based language server. You can also add debug flags here. +* Add the flags `-agentlib:jdwp-transport=dt_socket,server=y,suspend=n,quiet=y,address=12345` to the `settings.json` of the VSCode lombok plugin, and then tell your debugger to attach to localhost:12345. +* Set the property `java.server.launchMode` to `"Standard"`. +* Consider activing the language server debug mode. + diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index b8cd442ace..05550a06b0 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 @@ 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; @@ -558,6 +559,15 @@ private 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.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. + * 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.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 9f3a471f9f..07d035c58b 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 @@ private void buildWithCollection(Class nodeType, Object collection, Collectio } } + /** + * @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 final T readConfiguration(ConfigurationKey key) { 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/Version.java b/src/core/lombok/core/Version.java index eb8ed6e735..dafe17aeee 100644 --- a/src/core/lombok/core/Version.java +++ b/src/core/lombok/core/Version.java @@ -30,7 +30,7 @@ public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). // Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example. // Official builds always end in an even number. (Since 0.10.2). - private static final String VERSION = "1.18.21"; + private static final String VERSION = "1.18.23"; private static final String RELEASE_NAME = "Edgy Guinea Pig"; // private static final String RELEASE_NAME = "Envious Ferret"; diff --git a/src/core/lombok/core/configuration/CapitalizationStrategy.java b/src/core/lombok/core/configuration/CapitalizationStrategy.java new file mode 100644 index 0000000000..affd357646 --- /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 8717c22b93..293a2f1db8 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 f57d83c2c4..f90a7caf16 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.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; @@ -431,6 +432,7 @@ public static int primeForNull() { "com.fasterxml.jackson.annotation.JsonSetter", "com.fasterxml.jackson.annotation.JsonSubTypes", "com.fasterxml.jackson.annotation.JsonTypeInfo", + "com.fasterxml.jackson.annotation.JsonUnwrapped", "com.fasterxml.jackson.annotation.JsonView", "com.fasterxml.jackson.databind.annotation.JsonDeserialize", "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper", @@ -692,11 +694,13 @@ private static String toAccessorName(AST ast, AnnotationValues prefix = explicitPrefix ? Arrays.asList(ac.prefix()) : ast.readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX); boolean fluent = explicitFluent ? ac.fluent() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT)); + CapitalizationStrategy capitalizationStrategy = ast.readConfigurationOr(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION, CapitalizationStrategy.defaultValue()); fieldName = removePrefix(fieldName, prefix); if (fieldName == null) return null; @@ -709,7 +713,7 @@ private static String toAccessorName(AST ast, AnnotationValues toAllAccessorNames(AST ast, AnnotationValue 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)); + CapitalizationStrategy capitalizationStrategy = ast.readConfigurationOr(ConfigurationKeys.ACCESSORS_JAVA_BEANS_SPEC_CAPITALIZATION, CapitalizationStrategy.defaultValue()); fieldName = removePrefix(fieldName, prefix); if (fieldName == null) return Collections.emptyList(); @@ -798,8 +803,8 @@ private static List toAllAccessorNames(AST ast, AnnotationValue if (adhereToFluent && fluent) { names.add(baseName); } else { - names.add(buildAccessorName(normalPrefix, baseName)); - if (!normalPrefix.equals(booleanPrefix)) names.add(buildAccessorName(booleanPrefix, baseName)); + names.add(buildAccessorName(normalPrefix, baseName, capitalizationStrategy)); + if (!normalPrefix.equals(booleanPrefix)) names.add(buildAccessorName(booleanPrefix, baseName, capitalizationStrategy)); } } @@ -825,23 +830,36 @@ private static List toBaseNames(CharSequence fieldName, boolean isBoolea } /** + * @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) { + 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 capitalizationStrategy Which strategy to use to capitalize the name part. + */ + 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)) { - boolean useUpperCase = suffix.length() > 2 && - (Character.isTitleCase(suffix.charAt(1)) || Character.isUpperCase(suffix.charAt(1))); - 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/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java index 4f86f0a526..4950aeef27 100644 --- a/src/core/lombok/eclipse/EclipseNode.java +++ b/src/core/lombok/eclipse/EclipseNode.java @@ -215,13 +215,16 @@ private Integer getModifiers() { @Override public boolean isStatic() { if (node instanceof TypeDeclaration) { + TypeDeclaration t = (TypeDeclaration) node; + int f = t.modifiers; + if (((ClassFileConstants.AccInterface | ClassFileConstants.AccEnum) & f) != 0) return true; + EclipseNode directUp = directUp(); if (directUp == null || directUp.getKind() == Kind.COMPILATION_UNIT) return true; if (!(directUp.get() instanceof TypeDeclaration)) return false; TypeDeclaration p = (TypeDeclaration) directUp.get(); - int f = p.modifiers; - if ((ClassFileConstants.AccInterface & f) != 0) return true; - if ((ClassFileConstants.AccEnum & f) != 0) return true; + f = p.modifiers; + if (((ClassFileConstants.AccInterface | ClassFileConstants.AccEnum) & f) != 0) return true; } if (node instanceof FieldDeclaration) { diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 5eea980cc1..f8cde6c812 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.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 @@ static class EclipseReflectiveMembers { 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 @@ static class EclipseReflectiveMembers { 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) { @@ -1042,7 +1047,7 @@ public static char[][] getQualifiedInnerName(EclipseNode parent, char[] name) { 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(); @@ -2052,11 +2057,7 @@ static Annotation[] addAnnotation(ASTNode source, Annotation[] originalAnnotatio } 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); @@ -2635,6 +2636,13 @@ public static boolean isClassOrEnum(EclipseNode typeNode) { 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 +2670,21 @@ static boolean isTypeAndDoesNotHaveFlags(EclipseNode typeNode, long flags) { 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 { @@ -2713,7 +2736,14 @@ public static void setDocComment(CompilationUnitDeclaration cud, EclipseNode ecl 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/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index dab774f30b..2bfe1e8b96 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -293,6 +293,11 @@ private static final char[] prefixWith(char[] prefix, char[] name) { 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); @@ -660,7 +665,7 @@ private MethodDeclaration generateToBuilderMethod(BuilderJob job, TypeParameter[ 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]; @@ -1028,9 +1033,9 @@ private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData 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/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 12a3c315e6..a5e8dfb5a9 100755 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -538,14 +538,15 @@ public TypeReference createTypeReference(EclipseNode type, long p, ASTNode sourc if (addWildcards) genericsCount.add(arraySizeOf(((TypeDeclaration) type.get()).typeParameters)); boolean staticContext = (((TypeDeclaration) type.get()).modifiers & ClassFileConstants.AccStatic) != 0; EclipseNode tNode = type.up(); - if (!staticContext && tNode.getKind() == Kind.TYPE && (((TypeDeclaration) tNode.get()).modifiers & ClassFileConstants.AccInterface) != 0) staticContext = true; while (tNode != null && tNode.getKind() == Kind.TYPE) { + TypeDeclaration td = (TypeDeclaration) tNode.get(); + if (td.name == null || td.name.length == 0) break; list.add(tNode.getName()); - if (addWildcards) genericsCount.add(staticContext ? 0 : arraySizeOf(((TypeDeclaration) tNode.get()).typeParameters)); - if (!staticContext) staticContext = (((TypeDeclaration) tNode.get()).modifiers & Modifier.STATIC) != 0; + if (!staticContext && tNode.getKind() == Kind.TYPE && (td.modifiers & ClassFileConstants.AccInterface) != 0) staticContext = true; + if (addWildcards) genericsCount.add(staticContext ? 0 : arraySizeOf(td.typeParameters)); + if (!staticContext) staticContext = (td.modifiers & Modifier.STATIC) != 0; tNode = tNode.up(); - if (!staticContext && tNode.getKind() == Kind.TYPE && (((TypeDeclaration) tNode.get()).modifiers & ClassFileConstants.AccInterface) != 0) staticContext = true; } Collections.reverse(list); if (addWildcards) Collections.reverse(genericsCount); diff --git a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java index 5900e7edf0..3297ba0620 100644 --- a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java @@ -160,6 +160,8 @@ public void setFieldDefaultsForField(EclipseNode fieldNode, ASTNode pos, AccessL 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/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java index cc1a5c3fc6..071dcdfb4c 100644 --- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java @@ -60,14 +60,12 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler 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 @@ private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate 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/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index f58de60f7c..0919c7d43b 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -228,7 +228,7 @@ void traverseChildren(JavacASTVisitor visitor, JavacNode node) { 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/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 035f7c53db..fca0d0d1f7 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -286,13 +286,15 @@ private JCModifiers getModifiers() { @Override public boolean isStatic() { if (node instanceof JCClassDecl) { + JCClassDecl t = (JCClassDecl) node; + long f = t.mods.flags; + if (((Flags.INTERFACE | Flags.ENUM) & f) != 0) return true; JavacNode directUp = directUp(); if (directUp == null || directUp.getKind() == Kind.COMPILATION_UNIT) return true; if (!(directUp.get() instanceof JCClassDecl)) return false; JCClassDecl p = (JCClassDecl) directUp.get(); - long f = p.mods.flags; - if ((Flags.INTERFACE & f) != 0) return true; - if ((Flags.ENUM & f) != 0) return true; + f = p.mods.flags; + if (((Flags.INTERFACE | Flags.ENUM) & f) != 0) return true; } if (node instanceof JCVariableDecl) { diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index c23dc14c34..d8fdfb1bff 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -234,6 +234,11 @@ static class BuilderFieldData { ArrayList nonFinalNonDefaultedFields = null; + if (!isStaticAllowed(upToTypeNode(parent))) { + annotationNode.addError("@Builder is not supported on non-static nested classes."); + return; + } + if (parent.get() instanceof JCClassDecl) { if (!isClass(parent) && !isRecord(parent)) { annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR); @@ -631,7 +636,7 @@ private JCMethodDecl generateToBuilderMethod(BuilderJob job, List annotation, JCAnnotation ast, 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; JCClassDecl td = (JCClassDecl) parent.get(); @@ -773,7 +777,7 @@ private JCExpressionStatement createSetterCallWithInstanceValue(BuilderFieldData 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; @@ -945,7 +949,7 @@ private void generateSetterMethodsForBuilder(final SuperBuilderJob job, BuilderF } 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/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 3fc6a4e484..249993ee30 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -44,7 +44,6 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; import com.sun.tools.javac.tree.JCTree.JCBlock; -import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; @@ -252,10 +251,10 @@ static JCMethodDecl createToString(JavacNode typeNode, Collection= 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/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 78c20d39a3..a41264e801 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -106,6 +106,7 @@ import lombok.javac.JavacAugments; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; +import lombok.javac.JavacTreeMaker.TypeTag; import lombok.permit.Permit; /** @@ -1286,6 +1287,7 @@ static class EnterReflect { static Type classEnter(JCTree tree, JavacNode parent) { Enter enter = Enter.instance(parent.getContext()); Env classEnv = enter.getEnv((TypeSymbol) parent.getElement()); + if (classEnv == null) return null; Type type = (Type) Permit.invokeSneaky(classEnter, enter, tree, classEnv); if (type == null) return null; type.complete(); @@ -1902,7 +1904,7 @@ public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker make public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, JavacNode parentType, Name typeName, boolean instance, List params, List annotations) { JCExpression r = null; - if (parentType != null && parentType.getKind() == Kind.TYPE) { + if (parentType != null && parentType.getKind() == Kind.TYPE && !parentType.getName().isEmpty()) { JCClassDecl td = (JCClassDecl) parentType.get(); boolean outerInstance = instance && ((td.mods.flags & Flags.STATIC) == 0); List outerParams = instance ? td.typarams : List.nil(); @@ -1978,6 +1980,13 @@ public static boolean isClassOrEnum(JavacNode typeNode) { return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION | RECORD); } + /** + * 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(JavacNode typeNode) { + return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION); + } + /** * Returns {@code true} if the provided node is a record declaration (so, not an annotation definition, interface, enum, or plain class). */ @@ -1994,6 +2003,21 @@ public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, long flags) return (typeDeclflags & flags) == 0; } + /** + * 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; + } + public static JavacNode upToTypeNode(JavacNode node) { if (node == null) throw new NullPointerException("node"); while ((node != null) && !(node.get() instanceof JCClassDecl)) node = node.up(); @@ -2028,7 +2052,9 @@ public static JCExpression cloneType(JavacTreeMaker maker, JCExpression in, Java private static JCExpression cloneType0(JavacTreeMaker maker, JCTree in) { if (in == null) return null; - if (in instanceof JCPrimitiveTypeTree) return (JCExpression) in; + if (in instanceof JCPrimitiveTypeTree) { + return maker.TypeIdent(TypeTag.typeTag(in)); + } if (in instanceof JCIdent) { return maker.Ident(((JCIdent) in).name); diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index 4ca09b82f9..77fcd4eaf3 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -300,7 +300,7 @@ private void generateClearMethod(CheckerFrameworkVersion cfv, boolean deprecate, 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 @@ private void generateSingularMethod(CheckerFrameworkVersion cfv, boolean depreca 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 @@ private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate 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/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 8d39f4479a..e4f1760222 100755 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -43,9 +43,9 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.IdentityHashMap; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -733,7 +733,7 @@ public boolean delombok() throws IOException { List roots = new ArrayList(); Map baseMap = new IdentityHashMap(); - Set processors = new HashSet(); + Set processors = new LinkedHashSet(); processors.add(new lombok.javac.apt.LombokProcessor()); processors.addAll(additionalAnnotationProcessors); diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java index bcf3f43187..605b939156 100644 --- a/src/delombok/lombok/delombok/PrettyPrinter.java +++ b/src/delombok/lombok/delombok/PrettyPrinter.java @@ -545,6 +545,12 @@ private Name name_value(Name someName) { print(tree.implementing, ", "); } + List permitting = readObject(tree, "permitting", List.nil()); + if (permitting.nonEmpty()) { + print(" permits "); + print(permitting, ", "); + } + println(" {"); indent++; printClassMembers(tree.defs, isEnum, isInterface); @@ -1016,6 +1022,8 @@ private void printModifierKeywords(JCModifiers tree) { if ((v & TRANSIENT) != 0) print("transient "); if ((v & NATIVE) != 0) print("native "); if ((v & ABSTRACT) != 0) print("abstract "); + if ((v & SEALED) != 0) print("sealed "); + if ((v & NON_SEALED) != 0) print("non-sealed "); if ((v & STRICTFP) != 0) print("strictfp "); if ((v & DEFAULT) != 0 && (v & INTERFACE) == 0) print("default "); } @@ -1324,13 +1332,16 @@ private void printModifierKeywords(JCModifiers tree) { @Override public void visitCase(JCCase tree) { // Starting with JDK12, switches allow multiple expressions per case, and can take the form of an expression (preview feature). - List pats = readObject(tree, "pats", null); // JDK 12+ + List pats = readObject(tree, "labels", null); // JDK 17+ + if (pats == null) { + pats = readObject(tree, "pats", null); // JDK 12-17 + } if (pats == null) { - JCExpression pat = readObject(tree, "pat", null); // JDK -11 - pats = pat == null ? List.nil() : List.of(pat); + JCTree pat = readObject(tree, "pat", null); // JDK -11 + pats = pat == null ? List.nil() : List.of(pat); } - if (pats.isEmpty()) { + if (pats.isEmpty() || pats.size() == 1 && pats.head.getClass().getName().endsWith("$JCDefaultCaseLabel")) { aPrint("default"); } else { aPrint("case "); @@ -1421,6 +1432,22 @@ void printBindingPattern(JCTree tree) { print((Name) readObject(var, "name", null)); } + void printDefaultCase(JCTree tree) { + print("default"); + } + + void printGuardPattern(JCTree tree) { + print((JCTree) readObject(tree, "patt", null)); + print(" && "); + print((JCExpression) readObject(tree, "expr", null)); + } + + void printParenthesizedPattern(JCTree tree) { + print("("); + print((JCTree) readObject(tree, "pattern", null)); + print(")"); + } + @Override public void visitTry(JCTry tree) { aPrint("try "); List resources = readObject(tree, "resources", List.nil()); @@ -1639,6 +1666,12 @@ public void visitTypeBoundKind(TypeBoundKind tree) { printYieldExpression(tree); } else if (className.endsWith("$JCBindingPattern")) { // Introduced as preview in JDK14 printBindingPattern(tree); + } else if (className.endsWith("$JCDefaultCaseLabel")) { // Introduced in JDK17 + printDefaultCase(tree); + } else if (className.endsWith("$JCGuardPattern")) { // Introduced in JDK17 + printGuardPattern(tree); + } else if (className.endsWith("$JCParenthesizedPattern")) { // Introduced in JDK17 + printParenthesizedPattern(tree); } else { throw new AssertionError("Unhandled tree type: " + tree.getClass() + ": " + tree); } diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java index 0a11cd7adf..06e109607b 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java @@ -87,14 +87,14 @@ public String mapResourceName(int classFileFormatVersion, String resourceName) { patchHideGeneratedNodes(sm); patchPostCompileHookEclipse(sm); patchFixSourceTypeConverter(sm); - patchDisableLombokForCodeCleanup(sm); patchListRewriteHandleGeneratedMethods(sm); patchSyntaxAndOccurrencesHighlighting(sm); patchSortMembersOperation(sm); - patchExtractInterface(sm); + patchExtractInterfaceAndPullUp(sm); patchAboutDialog(sm); patchEclipseDebugPatches(sm); patchJavadoc(sm); + patchASTConverterLiterals(sm); patchPostCompileHookEcj(sm); @@ -134,7 +134,7 @@ private static void patchRenameField(ScriptManager sm) { .transplant().build()); } - private static void patchExtractInterface(ScriptManager sm) { + private static void patchExtractInterfaceAndPullUp(ScriptManager sm) { /* Fix sourceEnding for generated nodes to avoid null pointer */ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall() .target(new MethodTarget("org.eclipse.jdt.internal.compiler.SourceElementNotifier", "notifySourceElementRequestor", "void", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "org.eclipse.jdt.internal.compiler.ast.TypeDeclaration", "org.eclipse.jdt.internal.compiler.ast.ImportReference")) @@ -156,10 +156,31 @@ private static void patchExtractInterface(ScriptManager sm) { .requestExtra(StackRequest.THIS, StackRequest.PARAM4) .transplant().build()); - /* get real generated node in stead of a random one generated by the annotation */ + /* Get real node source instead of the annotation */ + sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall() + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.HierarchyProcessor", "createPlaceholderForSingleVariableDeclaration", "org.eclipse.jdt.core.dom.SingleVariableDeclaration", + "org.eclipse.jdt.core.dom.SingleVariableDeclaration", + "org.eclipse.jdt.core.ICompilationUnit", + "org.eclipse.jdt.core.dom.rewrite.ASTRewrite" + )) + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.HierarchyProcessor", "createPlaceholderForType", "org.eclipse.jdt.core.dom.Type", + "org.eclipse.jdt.core.dom.Type", + "org.eclipse.jdt.core.ICompilationUnit", + "org.eclipse.jdt.core.dom.rewrite.ASTRewrite" + )) + .methodToWrap(new Hook("org.eclipse.jdt.core.IBuffer", "getText", "java.lang.String", "int", "int")) + .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getRealNodeSource", "java.lang.String", "java.lang.String", "org.eclipse.jdt.core.dom.ASTNode")) + .requestExtra(StackRequest.PARAM1) + .transplant() + .build()); + + /* Get real generated node instead of a random one generated by the annotation */ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.replaceMethodCall() .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMemberDeclarations")) .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComments")) + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor", "createAbstractMethod")) + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor", "addMethodStubForAbstractMethod")) + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor", "createChangeManager")) .methodToReplace(new Hook("org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil", "getMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit")) .replacementMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getRealMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit")) .transplant().build()); @@ -177,6 +198,29 @@ private static void patchExtractInterface(ScriptManager sm) { .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode")) .request(StackRequest.PARAM2) .transplant().build()); + + /* Do not add a modifier to the generating annotation during pull up + * + * Example: Pull up a protected method (canEqual()/@EqualsAndHashCode) + */ + sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly() + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor$IncomingMemberVisibilityAdjustment", "rewriteVisibility")) + .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "skipRewriteVisibility", "boolean", "org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor$IncomingMemberVisibilityAdjustment")) + .request(StackRequest.THIS) + .transplant() + .build()); + + /* + * ImportRemover sometimes removes lombok imports if a generated method/type gets changed. Skipping all generated nodes fixes this behavior. + * + * Example: Create a class (Use.java) that uses a generated method (Test t; t.toString();) and pull up this generated method. + */ + sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly() + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ImportRemover", "registerRemovedNode", "void", "org.eclipse.jdt.core.dom.ASTNode")) + .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode")) + .request(StackRequest.PARAM1) + .transplant() + .build()); } private static void patchAboutDialog(ScriptManager sm) { @@ -200,20 +244,13 @@ private static void patchSyntaxAndOccurrencesHighlighting(ScriptManager sm) { .target(new MethodTarget("org.eclipse.jdt.internal.ui.search.OccurrencesFinder", "addUsage")) .target(new MethodTarget("org.eclipse.jdt.internal.ui.search.OccurrencesFinder", "addWrite")) .target(new MethodTarget("org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingReconciler$PositionCollector", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName")) + .target(new MethodTarget("org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingReconciler$PositionCollector", "visitLiteral", "boolean", "org.eclipse.jdt.core.dom.Expression")) .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode")) .valueMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "returnFalse", "boolean", "java.lang.Object")) .request(StackRequest.PARAM1) .build()); } - private static void patchDisableLombokForCodeCleanup(ScriptManager sm) { - sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly() - .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTNode", "accept", "void", "org.eclipse.jdt.core.dom.ASTVisitor")) - .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isRefactoringVisitorAndGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.core.dom.ASTVisitor")) - .request(StackRequest.THIS, StackRequest.PARAM1) - .build()); - } - private static void patchListRewriteHandleGeneratedMethods(ScriptManager sm) { sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.replaceMethodCall() .target(new MethodTarget("org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer$ListRewriter", "rewriteList")) @@ -308,6 +345,12 @@ private static void patchHideGeneratedNodes(ScriptManager sm) { "org.eclipse.jdt.core.dom.SimpleName[]")) .request(StackRequest.RETURN_VALUE).build()); + sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly() + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTNode", "accept", "void", "org.eclipse.jdt.core.dom.ASTVisitor")) + .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isBlockedVisitorAndGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.core.dom.ASTVisitor")) + .request(StackRequest.THIS, StackRequest.PARAM1) + .build()); + patchRefactorScripts(sm); patchFormatters(sm); } @@ -528,6 +571,13 @@ private static void patchSetGeneratedFlag(ScriptManager sm) { "org.eclipse.jdt.core.dom.Name", "java.lang.Object")) .transplant().build()); + sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall() + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration")) + .methodToWrap(new Hook("org.eclipse.jdt.core.dom.Block", "", "void", "org.eclipse.jdt.core.dom.AST")) + .requestExtra(StackRequest.PARAM2) + .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void", + "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode")) + .transplant().build()); sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall() .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.TypeReference")) @@ -766,6 +816,7 @@ private static void addPatchesForVal(ScriptManager sm) { sm.addScript(ScriptBuilder.replaceMethodCall() .target(new MethodTarget(LOCALDECLARATION_SIG, "resolve", "void", BLOCKSCOPE_SIG)) + .target(new MethodTarget(LOCALDECLARATION_SIG, "resolve", "void", BLOCKSCOPE_SIG, "boolean")) .methodToReplace(new Hook(EXPRESSION_SIG, "resolveType", TYPEBINDING_SIG, BLOCKSCOPE_SIG)) .requestExtra(StackRequest.THIS) .replacementMethod(new Hook("lombok.launch.PatchFixesHider$Val", "skipResolveInitializerIfAlreadyCalled2", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG, LOCALDECLARATION_SIG)) @@ -895,6 +946,14 @@ private static void patchJavadoc(ScriptManager sm) { .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")) @@ -919,4 +978,22 @@ private static void patchJavadoc(ScriptManager sm) { .build()); } + private static void patchASTConverterLiterals(ScriptManager sm) { + sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall() + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.Expression", "org.eclipse.jdt.internal.compiler.ast.StringLiteral")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.Expression", "org.eclipse.jdt.internal.compiler.ast.TextBlock")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.CharacterLiteral", "org.eclipse.jdt.internal.compiler.ast.CharLiteral")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.NumberLiteral", "org.eclipse.jdt.internal.compiler.ast.DoubleLiteral")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.NumberLiteral", "org.eclipse.jdt.internal.compiler.ast.FloatLiteral")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.NumberLiteral", "org.eclipse.jdt.internal.compiler.ast.LongLiteral")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.NumberLiteral", "org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.NumberLiteral", "org.eclipse.jdt.internal.compiler.ast.IntLiteral")) + .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.NumberLiteral", "org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue")) + .methodToWrap(new Hook("java.lang.String", "", "void", "char[]", "int", "int")) + .requestExtra(StackRequest.PARAM1) + .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getRealNodeSource", "java.lang.String", "java.lang.String", "org.eclipse.jdt.internal.compiler.ast.ASTNode")) + .transplant() + .build()); + } + } diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java index 5b34917e31..673c30fd25 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 @@ static final String getSignature(SourceMethod sourceMethod) { 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 @@ private static class Reflection { 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 @@ private static String javadoc2HTML(IMember member, IJavaElement element, String 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); diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java index 774e5b4007..e758979d27 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java @@ -35,13 +35,11 @@ import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; -import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; @@ -59,8 +57,8 @@ 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 { @@ -237,13 +235,19 @@ public static boolean handleValForLocalDeclaration(LocalDeclaration local, Block 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; } TypeBinding resolved = null; - Constant oldConstant = init.constant; try { resolved = decomponent ? getForEachComponentType(init, scope) : resolveForExpression(init, scope); } catch (NullPointerException e) { @@ -253,6 +257,46 @@ public static boolean handleValForLocalDeclaration(LocalDeclaration local, Block // just go with 'Object' and let the IDE print the appropriate errors. resolved = null; } + + if (resolved == null) { + if (init instanceof ConditionalExpression) { + ConditionalExpression cexp = (ConditionalExpression) init; + Expression ifTrue = cexp.valueIfTrue; + Expression ifFalse = cexp.valueIfFalse; + TypeBinding ifTrueResolvedType = ifTrue.resolvedType; + CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult; + CategorizedProblem[] problems = compilationResult.problems; + CategorizedProblem lastProblem = problems[compilationResult.problemCount - 1]; + if (ifTrueResolvedType != null && ifFalse.resolvedType == null && lastProblem.getCategoryID() == CAT_TYPE) { + int problemCount = compilationResult.problemCount; + for (int i = 0; i < problemCount; ++i) { + if (problems[i] == lastProblem) { + problems[i] = null; + if (i + 1 < problemCount) { + System.arraycopy(problems, i + 1, problems, i, problemCount - i + 1); + } + break; + } + } + compilationResult.removeProblem(lastProblem); + if (!compilationResult.hasErrors()) { + clearIgnoreFurtherInvestigationField(scope.referenceContext()); + setValue(getField(CompilationResult.class, "hasMandatoryErrors"), compilationResult, false); + } + + if (ifFalse instanceof FunctionalExpression) { + FunctionalExpression functionalExpression = (FunctionalExpression) ifFalse; + functionalExpression.setExpectedType(ifTrueResolvedType); + } + if (ifFalse.resolvedType == null) { + resolveForExpression(ifFalse, scope); + } + + resolved = ifTrueResolvedType; + } + } + } + if (resolved != null) { try { replacement = makeType(resolved, local.type, false); @@ -260,10 +304,6 @@ public static boolean handleValForLocalDeclaration(LocalDeclaration local, Block } catch (Exception e) { // Some type thing failed. } - } else { - if (init instanceof MessageSend && ((MessageSend) init).actualReceiverType == null) { - init.constant = oldConstant; - } } } @@ -281,6 +321,14 @@ private static boolean isVal(LocalDeclaration local, BlockScope scope) { 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 +336,8 @@ public static boolean handleValForForEach(ForeachStatement forEach, BlockScope s 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); @@ -353,43 +403,7 @@ private static TypeBinding resolveForExpression(Expression collection, BlockScop // Known cause of issues; for example: val e = mth("X"), where mth takes 2 arguments. return null; } catch (AbortCompilation e) { - if (collection instanceof ConditionalExpression) { - ConditionalExpression cexp = (ConditionalExpression) collection; - Expression ifTrue = cexp.valueIfTrue; - Expression ifFalse = cexp.valueIfFalse; - TypeBinding ifTrueResolvedType = ifTrue.resolvedType; - CategorizedProblem problem = e.problem; - if (ifTrueResolvedType != null && ifFalse.resolvedType == null && problem.getCategoryID() == CAT_TYPE) { - CompilationResult compilationResult = e.compilationResult; - CategorizedProblem[] problems = compilationResult.problems; - int problemCount = compilationResult.problemCount; - for (int i = 0; i < problemCount; ++i) { - if (problems[i] == problem) { - problems[i] = null; - if (i + 1 < problemCount) { - System.arraycopy(problems, i + 1, problems, i, problemCount - i + 1); - } - break; - } - } - compilationResult.removeProblem(problem); - if (!compilationResult.hasErrors()) { - clearIgnoreFurtherInvestigationField(scope.referenceContext()); - setValue(getField(CompilationResult.class, "hasMandatoryErrors"), compilationResult, false); - } - - if (ifFalse instanceof FunctionalExpression) { - FunctionalExpression functionalExpression = (FunctionalExpression) ifFalse; - functionalExpression.setExpectedType(ifTrueResolvedType); - } - if (ifFalse.resolvedType == null) { - ifFalse.resolve(scope); - } - - return ifTrueResolvedType; - } - } - throw e; + return null; } } diff --git a/src/eclipseAgent/lombok/launch/PatchFixesHider.java b/src/eclipseAgent/lombok/launch/PatchFixesHider.java index bee30922f5..63bb3747e8 100755 --- a/src/eclipseAgent/lombok/launch/PatchFixesHider.java +++ b/src/eclipseAgent/lombok/launch/PatchFixesHider.java @@ -57,6 +57,7 @@ import org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner; import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; +import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment; import static lombok.eclipse.EcjAugments.ASTNode_generatedBy; @@ -413,25 +414,27 @@ public static boolean isGenerated(org.eclipse.jdt.internal.compiler.ast.ASTNode } return result; } - - public static boolean isRefactoringVisitorAndGenerated(org.eclipse.jdt.core.dom.ASTNode node, org.eclipse.jdt.core.dom.ASTVisitor visitor) { - if (visitor == null) return false; - - String className = visitor.getClass().getName(); - if (!(className.startsWith("org.eclipse.jdt.internal.corext.fix") || className.startsWith("org.eclipse.jdt.internal.ui.fix"))) return false; - + + public static boolean isGenerated(org.eclipse.jdt.core.IMember member) { boolean result = false; try { - result = ((Boolean)node.getClass().getField("$isGenerated").get(node)).booleanValue(); - if (!result && node.getParent() != null && node.getParent() instanceof org.eclipse.jdt.core.dom.QualifiedName) { - result = isGenerated(node.getParent()); - } - } catch (Exception e) { + result = member.getNameRange().getLength() <= 0 || member.getNameRange().equals(member.getSourceRange()); + } catch (JavaModelException e) { // better to assume it isn't generated } return result; } + public static boolean isBlockedVisitorAndGenerated(org.eclipse.jdt.core.dom.ASTNode node, org.eclipse.jdt.core.dom.ASTVisitor visitor) { + if (visitor == null) return false; + + String className = visitor.getClass().getName(); + if (!(className.startsWith("org.eclipse.jdt.internal.corext.fix") || className.startsWith("org.eclipse.jdt.internal.ui.fix") || className.startsWith("org.eclipse.jdt.ls.core.internal.semantictokens.SemanticTokensVisitor"))) return false; + if (className.equals("org.eclipse.jdt.internal.corext.fix.VariableDeclarationFixCore$WrittenNamesFinder")) return false; + + return isGenerated(node); + } + public static boolean isListRewriteOnGeneratedNode(org.eclipse.jdt.core.dom.rewrite.ListRewrite rewrite) { return isGenerated(rewrite.getParent()); } @@ -473,8 +476,10 @@ public static java.lang.String getRealMethodDeclarationSource(java.lang.String o StringBuilder signature = new StringBuilder(); addAnnotations(annotations, signature); - if ((Boolean)processor.getClass().getDeclaredField("fPublic").get(processor)) signature.append("public "); - if ((Boolean)processor.getClass().getDeclaredField("fAbstract").get(processor)) signature.append("abstract "); + try { + if ((Boolean)processor.getClass().getDeclaredField("fPublic").get(processor)) signature.append("public "); + if ((Boolean)processor.getClass().getDeclaredField("fAbstract").get(processor)) signature.append("abstract "); + } catch (Throwable t) { } signature .append(declaration.getReturnType2().toString()) @@ -520,7 +525,7 @@ public static void addAnnotations(List anno for (Object value : normalAnn.values()) values.add(value.toString()); } - signature.append("@").append(annotation.resolveTypeBinding().getQualifiedName()); + signature.append("@").append(annotation.getTypeName().getFullyQualifiedName()); if (!values.isEmpty()) { signature.append("("); boolean first = true; @@ -696,7 +701,7 @@ public static int getTokenEndOffsetFixed(TokenScanner scanner, int token, int st public static IMethod[] removeGeneratedMethods(IMethod[] methods) throws Exception { List result = new ArrayList(); for (IMethod m : methods) { - if (m.getNameRange().getLength() > 0 && !m.getNameRange().equals(m.getSourceRange())) result.add(m); + if (!isGenerated(m)) result.add(m); } return result.size() == methods.length ? methods : result.toArray(new IMethod[0]); } @@ -799,5 +804,21 @@ public static Annotation[] convertAnnotations(Annotation[] out, IAnnotatable ann return replace; } + + public static String getRealNodeSource(String original, org.eclipse.jdt.internal.compiler.ast.ASTNode node) { + if (!isGenerated(node)) return original; + + return node.toString(); + } + + public static java.lang.String getRealNodeSource(java.lang.String original, org.eclipse.jdt.core.dom.ASTNode node) throws Exception { + if (!isGenerated(node)) return original; + + return node.toString(); + } + + public static boolean skipRewriteVisibility(IncomingMemberVisibilityAdjustment adjustment) { + return isGenerated(adjustment.getMember()); + } } } diff --git a/src/installer/lombok/installer/IdeLocation.java b/src/installer/lombok/installer/IdeLocation.java index 6b9a94c67d..7cba1e2a37 100644 --- a/src/installer/lombok/installer/IdeLocation.java +++ b/src/installer/lombok/installer/IdeLocation.java @@ -64,16 +64,4 @@ public static String canonical(File p) { return x == null ? p.getPath() : x; } } - - private static final String LEGAL_PATH_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/"; - private static final String LEGAL_PATH_CHARS_WINDOWS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,/;'[]{}!@#$^&()-_+= :\\"; - public static String escapePath(String path) { - StringBuilder out = new StringBuilder(); - String legalChars = OsUtils.getOS() == OsUtils.OS.UNIX ? LEGAL_PATH_CHARS : LEGAL_PATH_CHARS_WINDOWS; - for (char c : path.toCharArray()) { - if (legalChars.indexOf(c) == -1) out.append('\\'); - out.append(c); - } - return out.toString(); - } } diff --git a/src/installer/lombok/installer/eclipse/EclipseProductLocation.java b/src/installer/lombok/installer/eclipse/EclipseProductLocation.java index 73f98a3564..4cfd07f526 100644 --- a/src/installer/lombok/installer/eclipse/EclipseProductLocation.java +++ b/src/installer/lombok/installer/eclipse/EclipseProductLocation.java @@ -347,8 +347,10 @@ public String install() throws InstallException { pathPrefix = pathToLombokJarPrefix; } + // NB: You may be tempted to escape this, but don't; there is no possibility to escape this, but + // eclipse/java reads the string following the colon in 'raw' fashion. Spaces, colons - all works fine. newContents.append(String.format( - "-javaagent:%s", escapePath(pathPrefix + "lombok.jar"))).append(OS_NEWLINE); + "-javaagent:%s", pathPrefix + "lombok.jar")).append(OS_NEWLINE); FileOutputStream fos = new FileOutputStream(eclipseIniPath); try { diff --git a/src/installer/lombok/installer/eclipse/StandardProductDescriptor.java b/src/installer/lombok/installer/eclipse/StandardProductDescriptor.java index 9bd3ae9423..365bf7fbd6 100644 --- a/src/installer/lombok/installer/eclipse/StandardProductDescriptor.java +++ b/src/installer/lombok/installer/eclipse/StandardProductDescriptor.java @@ -35,6 +35,7 @@ public class StandardProductDescriptor implements EclipseProductDescriptor { private static final String USER_HOME = System.getProperty("user.home", "."); + private static final String[] BASE_WINDOWS_ROOTS = {"\\", "\\Program Files", "\\Program Files (x86)", "\\ProgramData\\Chocolatey\\lib"}; private static final String[] WINDOWS_ROOTS = windowsRoots(); private static final String[] MAC_ROOTS = {"/Applications", USER_HOME}; private static final String[] UNIX_ROOTS = {USER_HOME}; @@ -159,8 +160,11 @@ private static String concat(String base, String pathSeparator, String alternati private static String[] windowsRoots() { String localAppData = windowsLocalAppData(); - if (localAppData == null) return new String[] {"\\", "\\Program Files", "\\Program Files (x86)", USER_HOME}; - return new String[] {"\\", "\\Program Files", "\\Program Files (x86)", USER_HOME, localAppData}; + String[] out = new String[BASE_WINDOWS_ROOTS.length + (localAppData == null ? 1 : 2)]; + System.arraycopy(BASE_WINDOWS_ROOTS, 0, out, 0, BASE_WINDOWS_ROOTS.length); + out[BASE_WINDOWS_ROOTS.length] = USER_HOME; + if (localAppData != null) out[BASE_WINDOWS_ROOTS.length + 1] = localAppData; + return out; } private static String windowsLocalAppData() { diff --git a/src/utils/lombok/eclipse/Eclipse.java b/src/utils/lombok/eclipse/Eclipse.java index 8af481b99f..0f42ddc627 100644 --- a/src/utils/lombok/eclipse/Eclipse.java +++ b/src/utils/lombok/eclipse/Eclipse.java @@ -224,8 +224,11 @@ public static long getLatestEcjCompilerVersionConstant() { 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/Java14Flags.java b/src/utils/lombok/javac/Java14Flags.java deleted file mode 100644 index 0d565dcaab..0000000000 --- a/src/utils/lombok/javac/Java14Flags.java +++ /dev/null @@ -1,26 +0,0 @@ -package lombok.javac; - -public class Java14Flags { - private Java14Flags() { } - - /** - * Flag to indicate that a class is a record. The flag is also used to mark fields that are - * part of the state vector of a record and to mark the canonical constructor - */ - public static final long RECORD = 1L<<61; // ClassSymbols, MethodSymbols and VarSymbols - - /** - * Flag to mark a record constructor as a compact one - */ - public static final long COMPACT_RECORD_CONSTRUCTOR = 1L<<51; // MethodSymbols only - - /** - * Flag to mark a record field that was not initialized in the compact constructor - */ - public static final long UNINITIALIZED_FIELD= 1L<<51; // VarSymbols only - - /** Flag is set for compiler-generated record members, it could be appplied to - * accessors and fields - */ - public static final int GENERATED_MEMBER = 1<<24; // MethodSymbols and VarSymbols -} diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java index d9fcc4f2ad..3fa0fbb5fb 100644 --- a/src/utils/lombok/javac/Javac.java +++ b/src/utils/lombok/javac/Javac.java @@ -80,6 +80,8 @@ private Javac() { public static final long COMPACT_RECORD_CONSTRUCTOR = 1L << 51; // MethodSymbols (the 'implicit' many-args constructor that records have) public static final long UNINITIALIZED_FIELD = 1L << 51; // VarSymbols (To identify fields that the compact record constructor won't initialize) public static final long GENERATED_MEMBER = 1L << 24; // MethodSymbols, VarSymbols (marks methods and the constructor generated in records) + public static final long SEALED = 1L << 62; // ClassSymbols (Flag to indicate sealed class/interface declaration) + public static final long NON_SEALED = 1L << 63; // ClassSymbols (Flag to indicate that the class/interface was declared with the non-sealed modifier) /** * Returns the version of this java compiler, i.e. the JDK that it shipped in. For example, for javac v1.7, this returns {@code 7}. diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java index 30d7160685..d369b4e4c6 100644 --- a/src/utils/lombok/javac/JavacTreeMaker.java +++ b/src/utils/lombok/javac/JavacTreeMaker.java @@ -607,7 +607,19 @@ static Class classForName(Class context, String name) { public JCCase Case(JCExpression pat, List stats) { if (tryResolve(Case11)) return invoke(Case11, pat, stats); - return invoke(Case12.Case12, Case12.CASE_KIND_STATEMENT, pat == null ? com.sun.tools.javac.util.List.nil() : com.sun.tools.javac.util.List.of(pat), stats, null); + List labels; + if (pat == null) { + labels = tryResolve(DefaultCaseLabel) ? List.of(DefaultCaseLabel()) : List.nil(); + } else { + labels = List.of(pat); + } + return invoke(Case12.Case12, Case12.CASE_KIND_STATEMENT, labels, stats, null); + } + + //javac versions: 17 + private static final MethodId DefaultCaseLabel = MethodId("DefaultCaseLabel", JCTree.class); + public JCTree DefaultCaseLabel() { + return invoke(DefaultCaseLabel); } //javac versions: 6-8 diff --git a/src/utils/lombok/javac/TreeMirrorMaker.java b/src/utils/lombok/javac/TreeMirrorMaker.java index a67a4ec12f..44e26ab65a 100644 --- a/src/utils/lombok/javac/TreeMirrorMaker.java +++ b/src/utils/lombok/javac/TreeMirrorMaker.java @@ -32,8 +32,10 @@ import com.sun.source.tree.LabeledStatementTree; import com.sun.source.tree.VariableTree; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.TreeCopier; +import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; @@ -109,6 +111,21 @@ public Map getOriginalToCopyMap() { if (wipeSymAndType) { copy.sym = null; copy.type = null; + } else { + if (original.vartype != null) { + copy.vartype.type = original.vartype.type; + original.vartype.accept(new TreeScanner() { + @Override public void scan(JCTree tree) { + super.scan(tree); + originalToCopy.get(tree).type = tree.type; + } + + @Override public void visitSelect(JCFieldAccess tree) { + super.visitSelect(tree); + ((JCFieldAccess) originalToCopy.get(tree)).sym = tree.sym; + } + }); + } } } diff --git a/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java b/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java index f29f501b8e..e625cd8dc9 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 Scanner newScanner(CharSequence input, boolean keepDocComments) { 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/core/src/lombok/DirectoryRunner.java b/test/core/src/lombok/DirectoryRunner.java index b041c42efb..53347e2426 100644 --- a/test/core/src/lombok/DirectoryRunner.java +++ b/test/core/src/lombok/DirectoryRunner.java @@ -55,7 +55,8 @@ public enum Compiler { }, ECJ { @Override public int getVersion() { - return Eclipse.getEcjCompilerVersion(); + String javaVersionString = System.getProperty("compiler.compliance.level"); + return javaVersionString != null ? Integer.parseInt(javaVersionString) : Eclipse.getEcjCompilerVersion(); } }; diff --git a/test/core/src/lombok/LombokTestSource.java b/test/core/src/lombok/LombokTestSource.java index 0326dee9d3..27ffc31aec 100644 --- a/test/core/src/lombok/LombokTestSource.java +++ b/test/core/src/lombok/LombokTestSource.java @@ -161,6 +161,7 @@ private int[] parseVersionLimit(String spec) { private static final Pattern UNCHANGED_PATTERN = Pattern.compile("^\\s*unchanged\\s*(?:[-:].*)?$", Pattern.CASE_INSENSITIVE); private static final Pattern SKIP_COMPARE_CONTENT_PATTERN = Pattern.compile("^\\s*skip[- ]?compare[- ]?contents?\\s*(?:[-:].*)?$", Pattern.CASE_INSENSITIVE); private static final Pattern SKIP_IDEMPOTENT_PATTERN = Pattern.compile("^\\s*skip[- ]?idempotent\\s*(?:[-:].*)?$", Pattern.CASE_INSENSITIVE); + private static final Pattern ISSUE_REF_PATTERN = Pattern.compile("^\\s*issue #?\\d+(:?\\s+.*)?$", Pattern.CASE_INSENSITIVE); private LombokTestSource(File file, String content, List messages, List directives) { this.file = file; @@ -200,6 +201,9 @@ private LombokTestSource(File file, String content, List skipIdempotent = true; continue; } + if (ISSUE_REF_PATTERN.matcher(directive).matches()) { + continue; + } if (lc.startsWith("platform ")) { String platformDesc = lc.substring("platform ".length()); diff --git a/test/core/src/lombok/RunTestsViaDelombok.java b/test/core/src/lombok/RunTestsViaDelombok.java index 23a42c6716..e4eb1a3094 100644 --- a/test/core/src/lombok/RunTestsViaDelombok.java +++ b/test/core/src/lombok/RunTestsViaDelombok.java @@ -42,7 +42,6 @@ import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import com.sun.source.util.TreePath; @@ -211,8 +210,8 @@ public static class ValidateTypesProcessor extends TreeProcessor { } @Override public void visitVarDef(JCVariableDecl tree) { - // Skip non-field variables - if (!(parent instanceof JCClassDecl)) return; + // Skip local variables + if (!(parent instanceof JCClassDecl || parent instanceof JCMethodDecl)) return; validateSymbol(tree, tree.sym); super.visitVarDef(tree); @@ -222,8 +221,8 @@ private void validateSymbol(JCTree tree, Symbol sym) { if (sym == null) { fail("Missing symbol for " + tree); } - // Skip top level classes - if (sym.owner.getKind() == ElementKind.PACKAGE) return; + // Only classes have enclosed elements, skip everything else + if (!sym.owner.getKind().isClass()) return; if (!sym.owner.getEnclosedElements().contains(sym)) { fail(tree + " not added to parent"); diff --git a/test/core/src/lombok/RunTestsViaEcj.java b/test/core/src/lombok/RunTestsViaEcj.java index afba8c7f63..6137de494d 100644 --- a/test/core/src/lombok/RunTestsViaEcj.java +++ b/test/core/src/lombok/RunTestsViaEcj.java @@ -64,9 +64,22 @@ public class RunTestsViaEcj extends AbstractRunTests { protected CompilerOptions ecjCompilerOptions() { CompilerOptions options = new CompilerOptions(); - options.complianceLevel = Eclipse.getLatestEcjCompilerVersionConstant(); - options.sourceLevel = Eclipse.getLatestEcjCompilerVersionConstant(); - options.targetJDK = Eclipse.getLatestEcjCompilerVersionConstant(); + Map warnings = new HashMap(); + + String javaVersionString = System.getProperty("compiler.compliance.level"); + long ecjCompilerVersionConstant = Eclipse.getLatestEcjCompilerVersionConstant(); + long ecjCompilerVersion = Eclipse.getEcjCompilerVersion(); + if (javaVersionString != null) { + long javaVersion = Long.parseLong(javaVersionString); + ecjCompilerVersionConstant = (javaVersion + 44) << 16; + ecjCompilerVersion = javaVersion; + } else { + // Preview features are only allowed if the maximum compiler version is equal to the source version + warnings.put("org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures", "enabled"); + } + options.complianceLevel = ecjCompilerVersionConstant; + options.sourceLevel = ecjCompilerVersionConstant; + options.targetJDK = ecjCompilerVersionConstant; options.docCommentSupport = false; options.parseLiteralExpressionsAsConstants = true; options.inlineJsrBytecode = true; @@ -78,17 +91,14 @@ protected CompilerOptions ecjCompilerOptions() { options.reportUnusedParameterWhenOverridingConcrete = false; options.reportDeadCodeInTrivialIfStatement = false; options.generateClassFiles = false; - Map warnings = new HashMap(); warnings.put(CompilerOptions.OPTION_ReportUnusedLocal, "ignore"); warnings.put(CompilerOptions.OPTION_ReportUnusedLabel, "ignore"); warnings.put(CompilerOptions.OPTION_ReportUnusedImport, "ignore"); warnings.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, "ignore"); warnings.put(CompilerOptions.OPTION_ReportIndirectStaticAccess, "warning"); warnings.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, "warning"); - warnings.put("org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures", "enabled"); warnings.put("org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures", "ignore"); - int ecjVersion = Eclipse.getEcjCompilerVersion(); - warnings.put(CompilerOptions.OPTION_Source, (ecjVersion < 9 ? "1." : "") + ecjVersion); + warnings.put(CompilerOptions.OPTION_Source, (ecjCompilerVersion < 9 ? "1." : "") + ecjCompilerVersion); options.set(warnings); return options; } @@ -96,7 +106,7 @@ protected CompilerOptions ecjCompilerOptions() { protected IErrorHandlingPolicy ecjErrorHandlingPolicy() { return new IErrorHandlingPolicy() { public boolean stopOnFirstError() { - return true; + return false; } public boolean proceedOnErrors() { diff --git a/test/pretty/resource/after/Sealed.java b/test/pretty/resource/after/Sealed.java new file mode 100644 index 0000000000..1509603453 --- /dev/null +++ b/test/pretty/resource/after/Sealed.java @@ -0,0 +1,16 @@ +public class Sealed { + public abstract sealed class Parent permits Child1, Child2 { + } + + public final class Child1 extends Parent { + } + + public abstract non-sealed class Child2 extends Parent { + } + + public sealed interface SealedInterface permits ChildInterface1 { + } + + public non-sealed interface ChildInterface1 extends SealedInterface { + } +} \ No newline at end of file diff --git a/test/pretty/resource/after/Switch17.java b/test/pretty/resource/after/Switch17.java new file mode 100644 index 0000000000..038f2cd922 --- /dev/null +++ b/test/pretty/resource/after/Switch17.java @@ -0,0 +1,31 @@ +public class Switch17 { + String switchPatternMatching(Object o) { + return switch (o) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> o.toString(); + }; + } + + String switchNull(Object o) { + return switch (o) { + case null, default -> "?"; + }; + } + + String switchGuardPattern(Object o) { + return switch (o) { + case String s && s.length() > 1 -> s; + default -> o.toString(); + }; + } + + String switchParenthesizedPattern(Object o) { + return switch (o) { + case (String s) -> s; + default -> o.toString(); + }; + } +} \ No newline at end of file diff --git a/test/pretty/resource/after/ThisParameter.java b/test/pretty/resource/after/ThisParameter.java index 49452a5996..c57916becf 100644 --- a/test/pretty/resource/after/ThisParameter.java +++ b/test/pretty/resource/after/ThisParameter.java @@ -16,17 +16,17 @@ void classTagged(@ClassTagged("class") ThisParameter this) { void runtimeTagged(@RuntimeTagged("runtime") ThisParameter this) { // no content } - @Target(ElementType.PARAMETER) + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.SOURCE) @interface SourceTagged { String value(); } - @Target(ElementType.PARAMETER) + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.CLASS) @interface ClassTagged { String value(); } - @Target(ElementType.PARAMETER) + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME) @interface RuntimeTagged { String value(); diff --git a/test/pretty/resource/before/Sealed.java b/test/pretty/resource/before/Sealed.java new file mode 100644 index 0000000000..4682862710 --- /dev/null +++ b/test/pretty/resource/before/Sealed.java @@ -0,0 +1,17 @@ +// version 15: +public class Sealed { + public abstract sealed class Parent permits Child1, Child2 { + } + + public final class Child1 extends Parent { + } + + public abstract non-sealed class Child2 extends Parent { + } + + public sealed interface SealedInterface permits ChildInterface1 { + } + + public non-sealed interface ChildInterface1 extends SealedInterface { + } +} \ No newline at end of file diff --git a/test/pretty/resource/before/Switch17.java b/test/pretty/resource/before/Switch17.java new file mode 100644 index 0000000000..17754e8278 --- /dev/null +++ b/test/pretty/resource/before/Switch17.java @@ -0,0 +1,32 @@ +// version 17: +public class Switch17 { + String switchPatternMatching(Object o) { + return switch (o) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> o.toString(); + }; + } + + String switchNull(Object o) { + return switch (o) { + case null, default -> "?"; + }; + } + + String switchGuardPattern(Object o) { + return switch (o) { + case String s && s.length() > 1 -> s; + default -> o.toString(); + }; + } + + String switchParenthesizedPattern(Object o) { + return switch (o) { + case (String s) -> s; + default -> o.toString(); + }; + } +} diff --git a/test/pretty/resource/before/ThisParameter.java b/test/pretty/resource/before/ThisParameter.java index e37651cbd8..42e4237e87 100644 --- a/test/pretty/resource/before/ThisParameter.java +++ b/test/pretty/resource/before/ThisParameter.java @@ -1,4 +1,4 @@ -// version 9: the 'this' param option exists in java8, but is bugged, in that annotations are not allowed on them, even without a @Target. The only purpose of the this param is annotations, so, boy, isn't that a punch in the face? +// version 8: import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -22,19 +22,19 @@ void runtimeTagged(@RuntimeTagged("runtime") ThisParameter this) { // no content } - @Target(ElementType.PARAMETER) + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.SOURCE) @interface SourceTagged { String value(); } - @Target(ElementType.PARAMETER) + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.CLASS) @interface ClassTagged { String value(); } - @Target(ElementType.PARAMETER) + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME) @interface RuntimeTagged { String value(); diff --git a/test/pretty/resource/messages/DefaultMethod.java.messages b/test/pretty/resource/messages/DefaultMethod.java.messages new file mode 100644 index 0000000000..766c3d8c40 --- /dev/null +++ b/test/pretty/resource/messages/DefaultMethod.java.messages @@ -0,0 +1 @@ +OPTIONAL 9 as of release 17, all floating-point expressions are evaluated strictly and 'strictfp' is not required \ No newline at end of file diff --git a/test/pretty/resource/messages/ExoticJava.java.messages b/test/pretty/resource/messages/ExoticJava.java.messages new file mode 100644 index 0000000000..68e8d2811e --- /dev/null +++ b/test/pretty/resource/messages/ExoticJava.java.messages @@ -0,0 +1 @@ +OPTIONAL 16 as of release 17, all floating-point expressions are evaluated strictly and 'strictfp' is not required \ No newline at end of file diff --git a/test/transform/resource/after-delombok/AccessorsInAnonymousClass.java b/test/transform/resource/after-delombok/AccessorsInAnonymousClass.java new file mode 100644 index 0000000000..27fab50980 --- /dev/null +++ b/test/transform/resource/after-delombok/AccessorsInAnonymousClass.java @@ -0,0 +1,22 @@ +public class AccessorsInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + + @java.lang.SuppressWarnings("all") + public String string() { + return this.string; + } + + /** + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + public Inner string(final String string) { + this.string = string; + return this; + } + } + }; +} diff --git a/test/transform/resource/after-delombok/BuilderInAnonymousClass.java b/test/transform/resource/after-delombok/BuilderInAnonymousClass.java new file mode 100644 index 0000000000..4810a0a83d --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderInAnonymousClass.java @@ -0,0 +1,8 @@ +public class BuilderInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + } + }; +} diff --git a/test/transform/resource/after-delombok/BuilderNestedInEnum.java b/test/transform/resource/after-delombok/BuilderNestedInEnum.java new file mode 100644 index 0000000000..26dc2a0638 --- /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-delombok/BuilderWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/BuilderWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..4a21f2c305 --- /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/ConstructorsInAnonymousClass.java b/test/transform/resource/after-delombok/ConstructorsInAnonymousClass.java new file mode 100644 index 0000000000..7483718fcf --- /dev/null +++ b/test/transform/resource/after-delombok/ConstructorsInAnonymousClass.java @@ -0,0 +1,34 @@ +//version 8: +import lombok.NonNull; + +public class ConstructorsInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + @NonNull + private String string2; + + @java.lang.SuppressWarnings("all") + public Inner(final String string, @NonNull final String string2) { + if (string2 == null) { + throw new java.lang.NullPointerException("string2 is marked non-null but is null"); + } + this.string = string; + this.string2 = string2; + } + + @java.lang.SuppressWarnings("all") + public Inner(@NonNull final String string2) { + if (string2 == null) { + throw new java.lang.NullPointerException("string2 is marked non-null but is null"); + } + this.string2 = string2; + } + + @java.lang.SuppressWarnings("all") + public Inner() { + } + } + }; +} diff --git a/test/transform/resource/after-delombok/DataInAnonymousClass.java b/test/transform/resource/after-delombok/DataInAnonymousClass.java new file mode 100644 index 0000000000..788d7be529 --- /dev/null +++ b/test/transform/resource/after-delombok/DataInAnonymousClass.java @@ -0,0 +1,56 @@ +public class DataInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + + @java.lang.SuppressWarnings("all") + public Inner() { + } + + @java.lang.SuppressWarnings("all") + public String getString() { + return this.string; + } + + @java.lang.SuppressWarnings("all") + public void setString(final String string) { + this.string = string; + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof Inner)) return false; + final Inner other = (Inner) o; + if (!other.canEqual((java.lang.Object) this)) return false; + final java.lang.Object this$string = this.getString(); + final java.lang.Object other$string = other.getString(); + if (this$string == null ? other$string != null : !this$string.equals(other$string)) return false; + return true; + } + + @java.lang.SuppressWarnings("all") + protected boolean canEqual(final java.lang.Object other) { + return other instanceof Inner; + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + final java.lang.Object $string = this.getString(); + result = result * PRIME + ($string == null ? 43 : $string.hashCode()); + return result; + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "Inner(string=" + this.getString() + ")"; + } + } + }; +} diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeInAnonymousClass.java b/test/transform/resource/after-delombok/EqualsAndHashCodeInAnonymousClass.java new file mode 100644 index 0000000000..6f0b573850 --- /dev/null +++ b/test/transform/resource/after-delombok/EqualsAndHashCodeInAnonymousClass.java @@ -0,0 +1,36 @@ +public class EqualsAndHashCodeInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof Inner)) return false; + final Inner other = (Inner) o; + if (!other.canEqual((java.lang.Object) this)) return false; + final java.lang.Object this$string = this.string; + final java.lang.Object other$string = other.string; + if (this$string == null ? other$string != null : !this$string.equals(other$string)) return false; + return true; + } + + @java.lang.SuppressWarnings("all") + protected boolean canEqual(final java.lang.Object other) { + return other instanceof Inner; + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + final java.lang.Object $string = this.string; + result = result * PRIME + ($string == null ? 43 : $string.hashCode()); + return result; + } + } + }; +} diff --git a/test/transform/resource/after-delombok/FieldDefaultsViaConfigOnRecord.java b/test/transform/resource/after-delombok/FieldDefaultsViaConfigOnRecord.java new file mode 100644 index 0000000000..1a2ce88204 --- /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-delombok/FieldNameConstantsInAnonymousClass.java b/test/transform/resource/after-delombok/FieldNameConstantsInAnonymousClass.java new file mode 100644 index 0000000000..1f7e7d7a3e --- /dev/null +++ b/test/transform/resource/after-delombok/FieldNameConstantsInAnonymousClass.java @@ -0,0 +1,8 @@ +public class FieldNameConstantsInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + } + }; +} diff --git a/test/transform/resource/after-delombok/GetterInAnonymousClass.java b/test/transform/resource/after-delombok/GetterInAnonymousClass.java new file mode 100644 index 0000000000..3c99054532 --- /dev/null +++ b/test/transform/resource/after-delombok/GetterInAnonymousClass.java @@ -0,0 +1,13 @@ +public class GetterInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + + @java.lang.SuppressWarnings("all") + public String getString() { + return this.string; + } + } + }; +} diff --git a/test/transform/resource/after-delombok/GetterLazyInAnonymousClass.java b/test/transform/resource/after-delombok/GetterLazyInAnonymousClass.java new file mode 100644 index 0000000000..4476e463bd --- /dev/null +++ b/test/transform/resource/after-delombok/GetterLazyInAnonymousClass.java @@ -0,0 +1,24 @@ +public class GetterLazyInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private final java.util.concurrent.atomic.AtomicReference string = new java.util.concurrent.atomic.AtomicReference(); + + @java.lang.SuppressWarnings({"all", "unchecked"}) + public String getString() { + java.lang.Object value = this.string.get(); + if (value == null) { + synchronized (this.string) { + value = this.string.get(); + if (value == null) { + final String actualValue = "test"; + value = actualValue == null ? this.string : actualValue; + this.string.set(value); + } + } + } + return (String) (value == this.string ? null : value); + } + } + }; +} diff --git a/test/transform/resource/after-delombok/GetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/GetterWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..51ccfe630e --- /dev/null +++ b/test/transform/resource/after-delombok/GetterWithJavaBeansSpecCapitalization.java @@ -0,0 +1,12 @@ +class GetterWithJavaBeansSpecCapitalization { + int a; + int aField; + @java.lang.SuppressWarnings("all") + public int getA() { + return this.a; + } + @java.lang.SuppressWarnings("all") + public int getaField() { + return this.aField; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerSlf4jInAnonymousClass.java b/test/transform/resource/after-delombok/LoggerSlf4jInAnonymousClass.java new file mode 100644 index 0000000000..1ec25d927a --- /dev/null +++ b/test/transform/resource/after-delombok/LoggerSlf4jInAnonymousClass.java @@ -0,0 +1,7 @@ +public class LoggerSlf4jInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + } + }; +} diff --git a/test/transform/resource/after-delombok/SetterInAnonymousClass.java b/test/transform/resource/after-delombok/SetterInAnonymousClass.java new file mode 100644 index 0000000000..ced2be523a --- /dev/null +++ b/test/transform/resource/after-delombok/SetterInAnonymousClass.java @@ -0,0 +1,13 @@ +public class SetterInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + + @java.lang.SuppressWarnings("all") + public void setString(final String string) { + this.string = string; + } + } + }; +} diff --git a/test/transform/resource/after-delombok/SetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/SetterWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..de68ee60ae --- /dev/null +++ b/test/transform/resource/after-delombok/SetterWithJavaBeansSpecCapitalization.java @@ -0,0 +1,12 @@ +class SetterWithJavaBeansSpecCapitalization { + 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; + } +} diff --git a/test/transform/resource/after-delombok/SuperBuilderInAnonymousClass.java b/test/transform/resource/after-delombok/SuperBuilderInAnonymousClass.java new file mode 100644 index 0000000000..cc6549199a --- /dev/null +++ b/test/transform/resource/after-delombok/SuperBuilderInAnonymousClass.java @@ -0,0 +1,12 @@ +public class SuperBuilderInAnonymousClass { + Object annonymous = new Object() { + + class InnerParent { + private String string; + } + + class InnerChild { + private String string; + } + }; +} diff --git a/test/transform/resource/after-delombok/SynchronizedInAnonymousClass.java b/test/transform/resource/after-delombok/SynchronizedInAnonymousClass.java new file mode 100644 index 0000000000..904487a317 --- /dev/null +++ b/test/transform/resource/after-delombok/SynchronizedInAnonymousClass.java @@ -0,0 +1,15 @@ +public class SynchronizedInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + @java.lang.SuppressWarnings("all") + private final java.lang.Object $lock = new java.lang.Object[0]; + + public void foo() { + synchronized (this.$lock) { + String foo = "bar"; + } + } + } + }; +} diff --git a/test/transform/resource/after-delombok/ToStringInAnonymousClass.java b/test/transform/resource/after-delombok/ToStringInAnonymousClass.java new file mode 100644 index 0000000000..aa3651bb49 --- /dev/null +++ b/test/transform/resource/after-delombok/ToStringInAnonymousClass.java @@ -0,0 +1,14 @@ +public class ToStringInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "Inner(string=" + this.string + ")"; + } + } + }; +} diff --git a/test/transform/resource/after-delombok/UtilityClassInAnonymousClass.java b/test/transform/resource/after-delombok/UtilityClassInAnonymousClass.java new file mode 100644 index 0000000000..3df9b559aa --- /dev/null +++ b/test/transform/resource/after-delombok/UtilityClassInAnonymousClass.java @@ -0,0 +1,8 @@ +public class UtilityClassInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private String string; + } + }; +} diff --git a/test/transform/resource/after-delombok/ValAnonymousSubclassSelfReference.java b/test/transform/resource/after-delombok/ValAnonymousSubclassSelfReference.java new file mode 100644 index 0000000000..a1176a3c78 --- /dev/null +++ b/test/transform/resource/after-delombok/ValAnonymousSubclassSelfReference.java @@ -0,0 +1,17 @@ +import java.util.Map; +import java.util.HashMap; + +public class ValAnonymousSubclassSelfReference { + public void test(T arg) { + T d = arg; + Integer[] e = new Integer[1]; + int[] f = new int[0]; + java.util.Map g = new HashMap(); + Integer h = 0; + int i = 0; + final int j = 1; + final int k = 2; + new ValAnonymousSubclassSelfReference() { + }; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/ValInvalidParameter.java b/test/transform/resource/after-delombok/ValInvalidParameter.java new file mode 100644 index 0000000000..f3d4229ce8 --- /dev/null +++ b/test/transform/resource/after-delombok/ValInvalidParameter.java @@ -0,0 +1,29 @@ +public class ValInvalidParameter { + public void val() { + final java.lang.Object a = a(new NonExistingClass()); + final java.lang.Object b = a(a(new NonExistingClass())); + final java.lang.Object c = nonExisitingMethod(b(1)); + final java.lang.Object d = nonExistingObject.nonExistingMethod(); + final java.lang.Object e = b(1).nonExistingMethod(); + final java.lang.Object f = 1 > 2 ? a(new NonExistingClass()) : a(new NonExistingClass()); + final java.lang.Object g = b2(1); + final java.lang.Integer h = b2(a("a"), a(null)); + final int i = a(a(null)); + } + + public int a(String param) { + return 0; + } + + public int a(Integer param) { + return 0; + } + + public Integer b(int i) { + return i; + } + + public Integer b2(int i, int j) { + return i; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/ValSwitchExpression.java b/test/transform/resource/after-delombok/ValSwitchExpression.java index a8fa9b0f83..ba26c137ed 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 0000000000..64aff9e59b --- /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-delombok/ValueInAnonymousClass.java b/test/transform/resource/after-delombok/ValueInAnonymousClass.java new file mode 100644 index 0000000000..5bab409312 --- /dev/null +++ b/test/transform/resource/after-delombok/ValueInAnonymousClass.java @@ -0,0 +1,46 @@ +public class ValueInAnonymousClass { + Object annonymous = new Object() { + + final class Inner { + private final String string; + + @java.lang.SuppressWarnings("all") + public Inner(final String string) { + this.string = string; + } + + @java.lang.SuppressWarnings("all") + public String getString() { + return this.string; + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof Inner)) return false; + final Inner other = (Inner) o; + final java.lang.Object this$string = this.getString(); + final java.lang.Object other$string = other.getString(); + if (this$string == null ? other$string != null : !this$string.equals(other$string)) 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 $string = this.getString(); + result = result * PRIME + ($string == null ? 43 : $string.hashCode()); + return result; + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "Inner(string=" + this.getString() + ")"; + } + } + }; +} diff --git a/test/transform/resource/after-delombok/ValueWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/ValueWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..543481e84b --- /dev/null +++ b/test/transform/resource/after-delombok/ValueWithJavaBeansSpecCapitalization.java @@ -0,0 +1,33 @@ +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) { + if (o == this) return true; + if (!(o instanceof ValueWithJavaBeansSpecCapitalization)) return false; + final ValueWithJavaBeansSpecCapitalization other = (ValueWithJavaBeansSpecCapitalization) o; + if (this.getaField() != other.getaField()) return false; + return true; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.getaField(); + return result; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ValueWithJavaBeansSpecCapitalization(aField=" + this.getaField() + ")"; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/WithByInAnonymousClass.java b/test/transform/resource/after-delombok/WithByInAnonymousClass.java new file mode 100644 index 0000000000..d84955b614 --- /dev/null +++ b/test/transform/resource/after-delombok/WithByInAnonymousClass.java @@ -0,0 +1,17 @@ +//version 8: +public class WithByInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private Inner(String string) { + } + + private String string; + + @java.lang.SuppressWarnings("all") + public Inner withStringBy(final java.util.function.Function transformer) { + return new Inner(transformer.apply(this.string)); + } + } + }; +} diff --git a/test/transform/resource/after-delombok/WithInAnonymousClass.java b/test/transform/resource/after-delombok/WithInAnonymousClass.java new file mode 100644 index 0000000000..0249053331 --- /dev/null +++ b/test/transform/resource/after-delombok/WithInAnonymousClass.java @@ -0,0 +1,19 @@ +public class WithInAnonymousClass { + Object annonymous = new Object() { + + class Inner { + private Inner(String string) { + } + + private String string; + + /** + * @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 Inner withString(final String string) { + return this.string == string ? this : new Inner(string); + } + } + }; +} diff --git a/test/transform/resource/after-delombok/WithWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-delombok/WithWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..e3737848a8 --- /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/AccessorsInAnonymousClass.java b/test/transform/resource/after-ecj/AccessorsInAnonymousClass.java new file mode 100644 index 0000000000..34db4f2dce --- /dev/null +++ b/test/transform/resource/after-ecj/AccessorsInAnonymousClass.java @@ -0,0 +1,29 @@ +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +public class AccessorsInAnonymousClass { + Object annonymous = new Object() { + @Getter @Setter @Accessors(fluent = true) class Inner { + private String string; + Inner() { + super(); + } + public @java.lang.SuppressWarnings("all") String string() { + return this.string; + } + /** + * @return {@code this}. + */ + public @java.lang.SuppressWarnings("all") Inner string(final String string) { + this.string = string; + return this; + } + } + x() { + super(); + } + }; + public AccessorsInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/BuilderInAnonymousClass.java b/test/transform/resource/after-ecj/BuilderInAnonymousClass.java new file mode 100644 index 0000000000..6766082282 --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderInAnonymousClass.java @@ -0,0 +1,17 @@ +import lombok.Builder; +public class BuilderInAnonymousClass { + Object annonymous = new Object() { + @Builder class Inner { + private String string; + Inner() { + super(); + } + } + x() { + super(); + } + }; + public BuilderInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/BuilderNestedInEnum.java b/test/transform/resource/after-ecj/BuilderNestedInEnum.java new file mode 100644 index 0000000000..b3fb54f319 --- /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 diff --git a/test/transform/resource/after-ecj/BuilderWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/BuilderWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..1107254fea --- /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/ConstructorsInAnonymousClass.java b/test/transform/resource/after-ecj/ConstructorsInAnonymousClass.java new file mode 100644 index 0000000000..545ab04d0c --- /dev/null +++ b/test/transform/resource/after-ecj/ConstructorsInAnonymousClass.java @@ -0,0 +1,38 @@ +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +public class ConstructorsInAnonymousClass { + Object annonymous = new Object() { + @AllArgsConstructor @RequiredArgsConstructor @NoArgsConstructor class Inner { + private String string; + private @NonNull String string2; + public @java.lang.SuppressWarnings("all") Inner(final String string, final @NonNull String string2) { + super(); + if ((string2 == null)) + { + throw new java.lang.NullPointerException("string2 is marked non-null but is null"); + } + this.string = string; + this.string2 = string2; + } + public @java.lang.SuppressWarnings("all") Inner(final @NonNull String string2) { + super(); + if ((string2 == null)) + { + throw new java.lang.NullPointerException("string2 is marked non-null but is null"); + } + this.string2 = string2; + } + public @java.lang.SuppressWarnings("all") Inner() { + super(); + } + } + x() { + super(); + } + }; + public ConstructorsInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/DataInAnonymousClass.java b/test/transform/resource/after-ecj/DataInAnonymousClass.java new file mode 100644 index 0000000000..c6e22f8029 --- /dev/null +++ b/test/transform/resource/after-ecj/DataInAnonymousClass.java @@ -0,0 +1,50 @@ +import lombok.Data; +public class DataInAnonymousClass { + Object annonymous = new Object() { + @Data class Inner { + private String string; + public @java.lang.SuppressWarnings("all") String getString() { + return this.string; + } + public @java.lang.SuppressWarnings("all") void setString(final String string) { + this.string = string; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof Inner))) + return false; + final Inner other = (Inner) o; + if ((! other.canEqual((java.lang.Object) this))) + return false; + final java.lang.Object this$string = this.getString(); + final java.lang.Object other$string = other.getString(); + if (((this$string == null) ? (other$string != null) : (! this$string.equals(other$string)))) + return false; + return true; + } + protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) { + return (other instanceof Inner); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + final int PRIME = 59; + int result = 1; + final java.lang.Object $string = this.getString(); + result = ((result * PRIME) + (($string == null) ? 43 : $string.hashCode())); + return result; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("Inner(string=" + this.getString()) + ")"); + } + public @java.lang.SuppressWarnings("all") Inner() { + super(); + } + } + x() { + super(); + } + }; + public DataInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeInAnonymousClass.java b/test/transform/resource/after-ecj/EqualsAndHashCodeInAnonymousClass.java new file mode 100644 index 0000000000..e66850bb60 --- /dev/null +++ b/test/transform/resource/after-ecj/EqualsAndHashCodeInAnonymousClass.java @@ -0,0 +1,41 @@ +import lombok.EqualsAndHashCode; +public class EqualsAndHashCodeInAnonymousClass { + Object annonymous = new Object() { + @EqualsAndHashCode class Inner { + private String string; + Inner() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof Inner))) + return false; + final Inner other = (Inner) o; + if ((! other.canEqual((java.lang.Object) this))) + return false; + final java.lang.Object this$string = this.string; + final java.lang.Object other$string = other.string; + if (((this$string == null) ? (other$string != null) : (! this$string.equals(other$string)))) + return false; + return true; + } + protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) { + return (other instanceof Inner); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + final int PRIME = 59; + int result = 1; + final java.lang.Object $string = this.string; + result = ((result * PRIME) + (($string == null) ? 43 : $string.hashCode())); + return result; + } + } + x() { + super(); + } + }; + public EqualsAndHashCodeInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/FieldDefaultsViaConfigOnRecord.java b/test/transform/resource/after-ecj/FieldDefaultsViaConfigOnRecord.java new file mode 100644 index 0000000000..44ef0d4c8c --- /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/after-ecj/FieldNameConstantsInAnonymousClass.java b/test/transform/resource/after-ecj/FieldNameConstantsInAnonymousClass.java new file mode 100644 index 0000000000..b04bef517d --- /dev/null +++ b/test/transform/resource/after-ecj/FieldNameConstantsInAnonymousClass.java @@ -0,0 +1,17 @@ +import lombok.experimental.FieldNameConstants; +public class FieldNameConstantsInAnonymousClass { + Object annonymous = new Object() { + @FieldNameConstants class Inner { + private String string; + Inner() { + super(); + } + } + x() { + super(); + } + }; + public FieldNameConstantsInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/GetterInAnonymousClass.java b/test/transform/resource/after-ecj/GetterInAnonymousClass.java new file mode 100644 index 0000000000..30e6338dcb --- /dev/null +++ b/test/transform/resource/after-ecj/GetterInAnonymousClass.java @@ -0,0 +1,20 @@ +import lombok.Getter; +public class GetterInAnonymousClass { + Object annonymous = new Object() { + @Getter class Inner { + private String string; + Inner() { + super(); + } + public @java.lang.SuppressWarnings("all") String getString() { + return this.string; + } + } + x() { + super(); + } + }; + public GetterInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/GetterLazyInAnonymousClass.java b/test/transform/resource/after-ecj/GetterLazyInAnonymousClass.java new file mode 100644 index 0000000000..ab8bc5997c --- /dev/null +++ b/test/transform/resource/after-ecj/GetterLazyInAnonymousClass.java @@ -0,0 +1,34 @@ +import lombok.Getter; +public class GetterLazyInAnonymousClass { + Object annonymous = new Object() { + class Inner { + private final @Getter(lazy = true) java.util.concurrent.atomic.AtomicReference string = new java.util.concurrent.atomic.AtomicReference(); + Inner() { + super(); + } + public @java.lang.SuppressWarnings({"all", "unchecked"}) String getString() { + java.lang.Object value = this.string.get(); + if ((value == null)) + { + synchronized (this.string) + { + value = this.string.get(); + if ((value == null)) + { + final String actualValue = "test"; + value = ((actualValue == null) ? this.string : actualValue); + this.string.set(value); + } + } + } + return (String) ((value == this.string) ? null : value); + } + } + x() { + super(); + } + }; + public GetterLazyInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/GetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/GetterWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..745529a0d9 --- /dev/null +++ b/test/transform/resource/after-ecj/GetterWithJavaBeansSpecCapitalization.java @@ -0,0 +1,13 @@ +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/LoggerSlf4jInAnonymousClass.java b/test/transform/resource/after-ecj/LoggerSlf4jInAnonymousClass.java new file mode 100644 index 0000000000..0c78a28855 --- /dev/null +++ b/test/transform/resource/after-ecj/LoggerSlf4jInAnonymousClass.java @@ -0,0 +1,16 @@ +import lombok.extern.slf4j.Slf4j; +public class LoggerSlf4jInAnonymousClass { + Object annonymous = new Object() { + @Slf4j class Inner { + Inner() { + super(); + } + } + x() { + super(); + } + }; + public LoggerSlf4jInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/SetterInAnonymousClass.java b/test/transform/resource/after-ecj/SetterInAnonymousClass.java new file mode 100644 index 0000000000..fc0bf2d83b --- /dev/null +++ b/test/transform/resource/after-ecj/SetterInAnonymousClass.java @@ -0,0 +1,20 @@ +import lombok.Setter; +public class SetterInAnonymousClass { + Object annonymous = new Object() { + @Setter class Inner { + private String string; + Inner() { + super(); + } + public @java.lang.SuppressWarnings("all") void setString(final String string) { + this.string = string; + } + } + x() { + super(); + } + }; + public SetterInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/SetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/SetterWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..4e99890a85 --- /dev/null +++ b/test/transform/resource/after-ecj/SetterWithJavaBeansSpecCapitalization.java @@ -0,0 +1,13 @@ +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/SuperBuilderInAnonymousClass.java b/test/transform/resource/after-ecj/SuperBuilderInAnonymousClass.java new file mode 100644 index 0000000000..238f42dffe --- /dev/null +++ b/test/transform/resource/after-ecj/SuperBuilderInAnonymousClass.java @@ -0,0 +1,23 @@ +import lombok.experimental.SuperBuilder; +public class SuperBuilderInAnonymousClass { + Object annonymous = new Object() { + @SuperBuilder class InnerParent { + private String string; + InnerParent() { + super(); + } + } + @SuperBuilder class InnerChild { + private String string; + InnerChild() { + super(); + } + } + x() { + super(); + } + }; + public SuperBuilderInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/SynchronizedInAnonymousClass.java b/test/transform/resource/after-ecj/SynchronizedInAnonymousClass.java new file mode 100644 index 0000000000..77013f2fbd --- /dev/null +++ b/test/transform/resource/after-ecj/SynchronizedInAnonymousClass.java @@ -0,0 +1,23 @@ +import lombok.Synchronized; +public class SynchronizedInAnonymousClass { + Object annonymous = new Object() { + class Inner { + private final java.lang.Object $lock = new java.lang.Object[0]; + Inner() { + super(); + } + public @Synchronized void foo() { + synchronized (this.$lock) + { + String foo = "bar"; + } + } + } + x() { + super(); + } + }; + public SynchronizedInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/ToStringInAnonymousClass.java b/test/transform/resource/after-ecj/ToStringInAnonymousClass.java new file mode 100644 index 0000000000..02ad2a88fe --- /dev/null +++ b/test/transform/resource/after-ecj/ToStringInAnonymousClass.java @@ -0,0 +1,20 @@ +import lombok.ToString; +public class ToStringInAnonymousClass { + Object annonymous = new Object() { + @ToString class Inner { + private String string; + Inner() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("Inner(string=" + this.string) + ")"); + } + } + x() { + super(); + } + }; + public ToStringInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/UtilityClassInAnonymousClass.java b/test/transform/resource/after-ecj/UtilityClassInAnonymousClass.java new file mode 100644 index 0000000000..e836636d48 --- /dev/null +++ b/test/transform/resource/after-ecj/UtilityClassInAnonymousClass.java @@ -0,0 +1,17 @@ +import lombok.experimental.UtilityClass; +public class UtilityClassInAnonymousClass { + Object annonymous = new Object() { + @UtilityClass class Inner { + private String string; + Inner() { + super(); + } + } + x() { + super(); + } + }; + public UtilityClassInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/ValAnonymousSubclassSelfReference.java b/test/transform/resource/after-ecj/ValAnonymousSubclassSelfReference.java new file mode 100644 index 0000000000..12b0f6402f --- /dev/null +++ b/test/transform/resource/after-ecj/ValAnonymousSubclassSelfReference.java @@ -0,0 +1,23 @@ +import java.util.Map; +import java.util.HashMap; +import lombok.val; +public class ValAnonymousSubclassSelfReference { + public ValAnonymousSubclassSelfReference() { + super(); + } + public void test(T arg) { + T d = arg; + Integer[] e = new Integer[1]; + int[] f = new int[0]; + java.util.Map g = new HashMap(); + Integer h = 0; + int i = 0; + final @val int j = 1; + final @val int k = 2; + new ValAnonymousSubclassSelfReference() { + x() { + super(); + } + }; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValErrors.java b/test/transform/resource/after-ecj/ValErrors.java index 1bd61f87f6..19c2facd75 100644 --- a/test/transform/resource/after-ecj/ValErrors.java +++ b/test/transform/resource/after-ecj/ValErrors.java @@ -4,9 +4,9 @@ public ValErrors() { super(); } public void unresolvableExpression() { - val c = d; + final @val java.lang.Object c = d; } public void arrayInitializer() { - val e = {"foo", "bar"}; + final @val java.lang.Object e = {"foo", "bar"}; } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValInvalidParameter.java b/test/transform/resource/after-ecj/ValInvalidParameter.java new file mode 100644 index 0000000000..14549aa74d --- /dev/null +++ b/test/transform/resource/after-ecj/ValInvalidParameter.java @@ -0,0 +1,29 @@ +import lombok.val; +public class ValInvalidParameter { + public ValInvalidParameter() { + super(); + } + public void val() { + final @val java.lang.Object a = a(new NonExistingClass()); + final @val java.lang.Object b = a(a(new NonExistingClass())); + final @val java.lang.Object c = nonExisitingMethod(b(1)); + final @val java.lang.Object d = nonExistingObject.nonExistingMethod(); + final @val java.lang.Object e = b(1).nonExistingMethod(); + final @val java.lang.Object f = ((1 > 2) ? a(new NonExistingClass()) : a(new NonExistingClass())); + final @val java.lang.Object g = b2(1); + final @val java.lang.Object h = b2(a("a"), a(null)); + final @val java.lang.Object i = a(a(null)); + } + public int a(String param) { + return 0; + } + public int a(Integer param) { + return 0; + } + public Integer b(int i) { + return i; + } + public Integer b2(int i, int j) { + return i; + } +} \ 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 59b503cb6f..4e848572c8 100644 --- a/test/transform/resource/after-ecj/ValSwitchExpression.java +++ b/test/transform/resource/after-ecj/ValSwitchExpression.java @@ -5,10 +5,10 @@ public 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 0000000000..2c8d721cd3 --- /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/after-ecj/ValueInAnonymousClass.java b/test/transform/resource/after-ecj/ValueInAnonymousClass.java new file mode 100644 index 0000000000..49cf8fc2f8 --- /dev/null +++ b/test/transform/resource/after-ecj/ValueInAnonymousClass.java @@ -0,0 +1,43 @@ +import lombok.Value; +public class ValueInAnonymousClass { + Object annonymous = new Object() { + final @Value class Inner { + private final String string; + public @java.lang.SuppressWarnings("all") String getString() { + return this.string; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof Inner))) + return false; + final Inner other = (Inner) o; + final java.lang.Object this$string = this.getString(); + final java.lang.Object other$string = other.getString(); + if (((this$string == null) ? (other$string != null) : (! this$string.equals(other$string)))) + 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 $string = this.getString(); + result = ((result * PRIME) + (($string == null) ? 43 : $string.hashCode())); + return result; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("Inner(string=" + this.getString()) + ")"); + } + public @java.lang.SuppressWarnings("all") Inner(final String string) { + super(); + this.string = string; + } + } + x() { + super(); + } + }; + public ValueInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/ValueWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/ValueWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..8117dbb040 --- /dev/null +++ b/test/transform/resource/after-ecj/ValueWithJavaBeansSpecCapitalization.java @@ -0,0 +1,29 @@ +final @lombok.Value class ValueWithJavaBeansSpecCapitalization { + 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 ValueWithJavaBeansSpecCapitalization))) + return false; + final ValueWithJavaBeansSpecCapitalization other = (ValueWithJavaBeansSpecCapitalization) 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 (("ValueWithJavaBeansSpecCapitalization(aField=" + this.getaField()) + ")"); + } + public @java.lang.SuppressWarnings("all") ValueWithJavaBeansSpecCapitalization(final int aField) { + super(); + this.aField = aField; + } +} diff --git a/test/transform/resource/after-ecj/WithByInAnonymousClass.java b/test/transform/resource/after-ecj/WithByInAnonymousClass.java new file mode 100644 index 0000000000..1bc3e80c0a --- /dev/null +++ b/test/transform/resource/after-ecj/WithByInAnonymousClass.java @@ -0,0 +1,20 @@ +import lombok.experimental.WithBy; +public class WithByInAnonymousClass { + Object annonymous = new Object() { + @WithBy class Inner { + private String string; + private Inner(String string) { + super(); + } + public @java.lang.SuppressWarnings("all") Inner withStringBy(final java.util.function.Function transformer) { + return new Inner(transformer.apply(this.string)); + } + } + x() { + super(); + } + }; + public WithByInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/WithInAnonymousClass.java b/test/transform/resource/after-ecj/WithInAnonymousClass.java new file mode 100644 index 0000000000..fef9602280 --- /dev/null +++ b/test/transform/resource/after-ecj/WithInAnonymousClass.java @@ -0,0 +1,23 @@ +import lombok.With; +public class WithInAnonymousClass { + Object annonymous = new Object() { + @With class Inner { + private String string; + private Inner(String string) { + 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") Inner withString(final String string) { + return ((this.string == string) ? this : new Inner(string)); + } + } + x() { + super(); + } + }; + public WithInAnonymousClass() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/WithWithJavaBeansSpecCapitalization.java b/test/transform/resource/after-ecj/WithWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..fb035da4a3 --- /dev/null +++ b/test/transform/resource/after-ecj/WithWithJavaBeansSpecCapitalization.java @@ -0,0 +1,12 @@ +@lombok.With class WithWithJavaBeansSpecCapitalization { + 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/AccessorsInAnonymousClass.java b/test/transform/resource/before/AccessorsInAnonymousClass.java new file mode 100644 index 0000000000..0bbab1d651 --- /dev/null +++ b/test/transform/resource/before/AccessorsInAnonymousClass.java @@ -0,0 +1,14 @@ +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +public class AccessorsInAnonymousClass { + Object annonymous = new Object() { + @Getter + @Setter + @Accessors(fluent = true) + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/BuilderInAnonymousClass.java b/test/transform/resource/before/BuilderInAnonymousClass.java new file mode 100644 index 0000000000..8291e6784f --- /dev/null +++ b/test/transform/resource/before/BuilderInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.Builder; + +public class BuilderInAnonymousClass { + Object annonymous = new Object() { + @Builder + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/BuilderNestedInEnum.java b/test/transform/resource/before/BuilderNestedInEnum.java new file mode 100644 index 0000000000..99348002f0 --- /dev/null +++ b/test/transform/resource/before/BuilderNestedInEnum.java @@ -0,0 +1,12 @@ +// issue #3014: Builder check if its on a non-static inner class and errors if it is. But it was erroring here even though it is on a static inner class. +class BuilderNestedInEnum { + public enum TestEnum { + FOO, BAR; + + @lombok.Builder + @lombok.Value + public static class TestBuilder { + String field; + } + } +} \ No newline at end of file diff --git a/test/transform/resource/before/BuilderWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/BuilderWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..db1fe15ffa --- /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/ConstructorsInAnonymousClass.java b/test/transform/resource/before/ConstructorsInAnonymousClass.java new file mode 100644 index 0000000000..a74a7f110b --- /dev/null +++ b/test/transform/resource/before/ConstructorsInAnonymousClass.java @@ -0,0 +1,18 @@ +//version 8: +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +public class ConstructorsInAnonymousClass { + Object annonymous = new Object() { + @AllArgsConstructor + @RequiredArgsConstructor + @NoArgsConstructor + class Inner { + private String string; + @NonNull + private String string2; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/DataInAnonymousClass.java b/test/transform/resource/before/DataInAnonymousClass.java new file mode 100644 index 0000000000..3de5ac0b78 --- /dev/null +++ b/test/transform/resource/before/DataInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.Data; + +public class DataInAnonymousClass { + Object annonymous = new Object() { + @Data + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/EqualsAndHashCodeInAnonymousClass.java b/test/transform/resource/before/EqualsAndHashCodeInAnonymousClass.java new file mode 100644 index 0000000000..0f0995b606 --- /dev/null +++ b/test/transform/resource/before/EqualsAndHashCodeInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.EqualsAndHashCode; + +public class EqualsAndHashCodeInAnonymousClass { + Object annonymous = new Object() { + @EqualsAndHashCode + class Inner { + private String string; + } + }; +} \ 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 0000000000..e72179e97f --- /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 diff --git a/test/transform/resource/before/FieldNameConstantsInAnonymousClass.java b/test/transform/resource/before/FieldNameConstantsInAnonymousClass.java new file mode 100644 index 0000000000..86325ce5f1 --- /dev/null +++ b/test/transform/resource/before/FieldNameConstantsInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.experimental.FieldNameConstants; + +public class FieldNameConstantsInAnonymousClass { + Object annonymous = new Object() { + @FieldNameConstants + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/GetterInAnonymousClass.java b/test/transform/resource/before/GetterInAnonymousClass.java new file mode 100644 index 0000000000..e81950217a --- /dev/null +++ b/test/transform/resource/before/GetterInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.Getter; + +public class GetterInAnonymousClass { + Object annonymous = new Object() { + @Getter + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/GetterLazyInAnonymousClass.java b/test/transform/resource/before/GetterLazyInAnonymousClass.java new file mode 100644 index 0000000000..e342e6365d --- /dev/null +++ b/test/transform/resource/before/GetterLazyInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.Getter; + +public class GetterLazyInAnonymousClass { + Object annonymous = new Object() { + class Inner { + @Getter(lazy = true) + private final String string = "test"; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/GetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/GetterWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..68f41e3d23 --- /dev/null +++ b/test/transform/resource/before/GetterWithJavaBeansSpecCapitalization.java @@ -0,0 +1,5 @@ +//CONF: lombok.accessors.capitalization = beanspec +class GetterWithJavaBeansSpecCapitalization { + @lombok.Getter int a; + @lombok.Getter int aField; +} diff --git a/test/transform/resource/before/LoggerSlf4jInAnonymousClass.java b/test/transform/resource/before/LoggerSlf4jInAnonymousClass.java new file mode 100644 index 0000000000..4839c7aaec --- /dev/null +++ b/test/transform/resource/before/LoggerSlf4jInAnonymousClass.java @@ -0,0 +1,9 @@ +import lombok.extern.slf4j.Slf4j; + +public class LoggerSlf4jInAnonymousClass { + Object annonymous = new Object() { + @Slf4j + class Inner { + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/MixGetterVal.java b/test/transform/resource/before/MixGetterVal.java index 3f06b1a8a8..4568902b0e 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/SetterInAnonymousClass.java b/test/transform/resource/before/SetterInAnonymousClass.java new file mode 100644 index 0000000000..1b3c817b1b --- /dev/null +++ b/test/transform/resource/before/SetterInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.Setter; + +public class SetterInAnonymousClass { + Object annonymous = new Object() { + @Setter + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/SetterWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/SetterWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..b5e34ba714 --- /dev/null +++ b/test/transform/resource/before/SetterWithJavaBeansSpecCapitalization.java @@ -0,0 +1,5 @@ +//CONF: lombok.accessors.capitalization = beanspec +class SetterWithJavaBeansSpecCapitalization { + @lombok.Setter int a; + @lombok.Setter int aField; +} diff --git a/test/transform/resource/before/SuperBuilderInAnonymousClass.java b/test/transform/resource/before/SuperBuilderInAnonymousClass.java new file mode 100644 index 0000000000..bff871aaf4 --- /dev/null +++ b/test/transform/resource/before/SuperBuilderInAnonymousClass.java @@ -0,0 +1,15 @@ +import lombok.experimental.SuperBuilder; + +public class SuperBuilderInAnonymousClass { + Object annonymous = new Object() { + @SuperBuilder + class InnerParent { + private String string; + } + + @SuperBuilder + class InnerChild { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/SynchronizedInAnonymousClass.java b/test/transform/resource/before/SynchronizedInAnonymousClass.java new file mode 100644 index 0000000000..11c623ce9f --- /dev/null +++ b/test/transform/resource/before/SynchronizedInAnonymousClass.java @@ -0,0 +1,12 @@ +import lombok.Synchronized; + +public class SynchronizedInAnonymousClass { + Object annonymous = new Object() { + class Inner { + @Synchronized + public void foo() { + String foo = "bar"; + } + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/ToStringInAnonymousClass.java b/test/transform/resource/before/ToStringInAnonymousClass.java new file mode 100644 index 0000000000..87a7a6c1cf --- /dev/null +++ b/test/transform/resource/before/ToStringInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.ToString; + +public class ToStringInAnonymousClass { + Object annonymous = new Object() { + @ToString + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/TrickyTypeResolution.java b/test/transform/resource/before/TrickyTypeResolution.java index 94d97fe0f1..7f3866ee9a 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/UtilityClassInAnonymousClass.java b/test/transform/resource/before/UtilityClassInAnonymousClass.java new file mode 100644 index 0000000000..4175750202 --- /dev/null +++ b/test/transform/resource/before/UtilityClassInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.experimental.UtilityClass; + +public class UtilityClassInAnonymousClass { + Object annonymous = new Object() { + @UtilityClass + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/ValAnonymousSubclassSelfReference.java b/test/transform/resource/before/ValAnonymousSubclassSelfReference.java new file mode 100644 index 0000000000..b17c997a55 --- /dev/null +++ b/test/transform/resource/before/ValAnonymousSubclassSelfReference.java @@ -0,0 +1,22 @@ +// version :9 +// issue 2420: to trigger the problem 2 var/val, at least one normal variable and a anonymous self reference is required +import java.util.Map; +import java.util.HashMap; + +import lombok.val; + +public class ValAnonymousSubclassSelfReference { + public void test(T arg) { + T d = arg; + Integer[] e = new Integer[1]; + int[] f = new int[0]; + java.util.Map g = new HashMap(); + Integer h = 0; + int i = 0; + + val j = 1; + val k = 2; + + new ValAnonymousSubclassSelfReference() { }; + } +} \ No newline at end of file diff --git a/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java index c0f8157af6..a434ba9dff 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 e20124a2fc..f1898cfd8c 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 75124c3cfd..ded4b07417 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 3d1f082cca..8cfc2c3301 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 873837192e..290a1f7295 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 3c5af366f6..293c9bcedc 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 a109bcd3ef..b137f0d7a9 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 35332b34e3..f2c50139ec 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 6750d045e0..a13c79d283 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 1c333ebb4f..0f4e604b2e 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 a782006242..5c885f7938 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/ValInvalidParameter.java b/test/transform/resource/before/ValInvalidParameter.java new file mode 100644 index 0000000000..f4961c4e33 --- /dev/null +++ b/test/transform/resource/before/ValInvalidParameter.java @@ -0,0 +1,32 @@ +//version :9 +import lombok.val; + +public class ValInvalidParameter { + public void val() { + val a = a(new NonExistingClass()); + val b = a(a(new NonExistingClass())); + val c = nonExisitingMethod(b(1)); + val d = nonExistingObject.nonExistingMethod(); + val e = b(1).nonExistingMethod(); + val f = 1 > 2 ? a(new NonExistingClass()) : a(new NonExistingClass()); + val g = b2(1); + val h = b2(a("a"), a(null)); + val i = a(a(null)); + } + + public int a(String param) { + return 0; + } + + public int a(Integer param) { + return 0; + } + + public Integer b(int i) { + return i; + } + + public Integer b2(int i, int j) { + return i; + } +} \ No newline at end of file diff --git a/test/transform/resource/before/ValLambda.java b/test/transform/resource/before/ValLambda.java index e956bcd37e..8f55d22234 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 b81cc22c6a..1ed738cc27 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 509a4f8b2f..e3b55950b6 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 649bc0cd7f..c1610af3a7 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 1b29d37cb7..99b717356a 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 3ef8527ec4..fa47c536c2 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 04763be2fd..5d1911da1a 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 0000000000..3b4e6fa831 --- /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 f62feca61f..710e236bbb 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 f7c3402af0..9e15f937c5 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 572a1e7dd1..0d145aa920 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 d0532606b2..fdb30d3273 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/test/transform/resource/before/ValueInAnonymousClass.java b/test/transform/resource/before/ValueInAnonymousClass.java new file mode 100644 index 0000000000..c0bde2abc4 --- /dev/null +++ b/test/transform/resource/before/ValueInAnonymousClass.java @@ -0,0 +1,10 @@ +import lombok.Value; + +public class ValueInAnonymousClass { + Object annonymous = new Object() { + @Value + class Inner { + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/ValueWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/ValueWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..7c001f6e4f --- /dev/null +++ b/test/transform/resource/before/ValueWithJavaBeansSpecCapitalization.java @@ -0,0 +1,5 @@ +//CONF: lombok.accessors.capitalization = beanspec +@lombok.Value +class ValueWithJavaBeansSpecCapitalization { + final int aField; +} diff --git a/test/transform/resource/before/WithByInAnonymousClass.java b/test/transform/resource/before/WithByInAnonymousClass.java new file mode 100644 index 0000000000..afed6adf64 --- /dev/null +++ b/test/transform/resource/before/WithByInAnonymousClass.java @@ -0,0 +1,13 @@ +//version 8: +import lombok.experimental.WithBy; + +public class WithByInAnonymousClass { + Object annonymous = new Object() { + @WithBy + class Inner { + private Inner(String string) { } + + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/WithInAnonymousClass.java b/test/transform/resource/before/WithInAnonymousClass.java new file mode 100644 index 0000000000..daf1bce568 --- /dev/null +++ b/test/transform/resource/before/WithInAnonymousClass.java @@ -0,0 +1,12 @@ +import lombok.With; + +public class WithInAnonymousClass { + Object annonymous = new Object() { + @With + class Inner { + private Inner(String string) { } + + private String string; + } + }; +} \ No newline at end of file diff --git a/test/transform/resource/before/WithWithJavaBeansSpecCapitalization.java b/test/transform/resource/before/WithWithJavaBeansSpecCapitalization.java new file mode 100644 index 0000000000..ef4a78ad2a --- /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) { + } +} diff --git a/test/transform/resource/messages-delombok/BuilderInAnonymousClass.java.messages b/test/transform/resource/messages-delombok/BuilderInAnonymousClass.java.messages new file mode 100644 index 0000000000..7607e73496 --- /dev/null +++ b/test/transform/resource/messages-delombok/BuilderInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @Builder is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-delombok/FieldNameConstantsInAnonymousClass.java.messages b/test/transform/resource/messages-delombok/FieldNameConstantsInAnonymousClass.java.messages new file mode 100644 index 0000000000..b9d4887f50 --- /dev/null +++ b/test/transform/resource/messages-delombok/FieldNameConstantsInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @FieldNameConstants is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-delombok/LoggerSlf4jInAnonymousClass.java.messages b/test/transform/resource/messages-delombok/LoggerSlf4jInAnonymousClass.java.messages new file mode 100644 index 0000000000..d4da9f9971 --- /dev/null +++ b/test/transform/resource/messages-delombok/LoggerSlf4jInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @Slf4j is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-delombok/SuperBuilderInAnonymousClass.java.messages b/test/transform/resource/messages-delombok/SuperBuilderInAnonymousClass.java.messages new file mode 100644 index 0000000000..f0cf324359 --- /dev/null +++ b/test/transform/resource/messages-delombok/SuperBuilderInAnonymousClass.java.messages @@ -0,0 +1,2 @@ +5 @SuperBuilder is not supported on non-static nested classes. +10 @SuperBuilder is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-delombok/UtilityClassInAnonymousClass.java.messages b/test/transform/resource/messages-delombok/UtilityClassInAnonymousClass.java.messages new file mode 100644 index 0000000000..8884e02d2b --- /dev/null +++ b/test/transform/resource/messages-delombok/UtilityClassInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @UtilityClass automatically makes the class static, however, this class cannot be made static. diff --git a/test/transform/resource/messages-delombok/ValInvalidParameter.java.messages b/test/transform/resource/messages-delombok/ValInvalidParameter.java.messages new file mode 100644 index 0000000000..da0df31595 --- /dev/null +++ b/test/transform/resource/messages-delombok/ValInvalidParameter.java.messages @@ -0,0 +1 @@ +12 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved \ No newline at end of file diff --git a/test/transform/resource/messages-ecj/BuilderInAnonymousClass.java.messages b/test/transform/resource/messages-ecj/BuilderInAnonymousClass.java.messages new file mode 100644 index 0000000000..7607e73496 --- /dev/null +++ b/test/transform/resource/messages-ecj/BuilderInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @Builder is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-ecj/FieldNameConstantsInAnonymousClass.java.messages b/test/transform/resource/messages-ecj/FieldNameConstantsInAnonymousClass.java.messages new file mode 100644 index 0000000000..b9d4887f50 --- /dev/null +++ b/test/transform/resource/messages-ecj/FieldNameConstantsInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @FieldNameConstants is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-ecj/LoggerSlf4jInAnonymousClass.java.messages b/test/transform/resource/messages-ecj/LoggerSlf4jInAnonymousClass.java.messages new file mode 100644 index 0000000000..d4da9f9971 --- /dev/null +++ b/test/transform/resource/messages-ecj/LoggerSlf4jInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @Slf4j is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-ecj/SuperBuilderInAnonymousClass.java.messages b/test/transform/resource/messages-ecj/SuperBuilderInAnonymousClass.java.messages new file mode 100644 index 0000000000..f0cf324359 --- /dev/null +++ b/test/transform/resource/messages-ecj/SuperBuilderInAnonymousClass.java.messages @@ -0,0 +1,2 @@ +5 @SuperBuilder is not supported on non-static nested classes. +10 @SuperBuilder is not supported on non-static nested classes. diff --git a/test/transform/resource/messages-ecj/UtilityClassInAnonymousClass.java.messages b/test/transform/resource/messages-ecj/UtilityClassInAnonymousClass.java.messages new file mode 100644 index 0000000000..8884e02d2b --- /dev/null +++ b/test/transform/resource/messages-ecj/UtilityClassInAnonymousClass.java.messages @@ -0,0 +1 @@ +5 @UtilityClass automatically makes the class static, however, this class cannot be made static. diff --git a/test/transform/resource/messages-ecj/ValErrors.java.messages b/test/transform/resource/messages-ecj/ValErrors.java.messages index c4c769011e..9fcec493ae 100644 --- a/test/transform/resource/messages-ecj/ValErrors.java.messages +++ b/test/transform/resource/messages-ecj/ValErrors.java.messages @@ -1,2 +1,4 @@ -6 d cannot be resolved to a variable -10 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... }) +7 d cannot be resolved to a variable +7 d cannot be resolved or is not a field +11 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... }) +11 Type mismatch: cannot convert from String[] to Object \ No newline at end of file diff --git a/test/transform/resource/messages-ecj/ValInBasicFor.java.messages b/test/transform/resource/messages-ecj/ValInBasicFor.java.messages index b32eabe4f9..00bc643f31 100644 --- a/test/transform/resource/messages-ecj/ValInBasicFor.java.messages +++ b/test/transform/resource/messages-ecj/ValInBasicFor.java.messages @@ -1,2 +1,4 @@ -7 'val' is not allowed in old-style for loops -7 Type mismatch: cannot convert from int to val +8 'val' is not allowed in old-style for loops +8 Type mismatch: cannot convert from int to val +8 Type mismatch: cannot convert from String to val +8 Type mismatch: cannot convert from double to val \ No newline at end of file diff --git a/test/transform/resource/messages-ecj/ValInvalidParameter.java.messages b/test/transform/resource/messages-ecj/ValInvalidParameter.java.messages new file mode 100644 index 0000000000..cbf2d7c4e6 --- /dev/null +++ b/test/transform/resource/messages-ecj/ValInvalidParameter.java.messages @@ -0,0 +1,9 @@ +5 NonExistingClass cannot be resolved to a type +6 NonExistingClass cannot be resolved to a type +7 The method nonExisitingMethod(Integer) is undefined for the type ValInvalidParameter +8 nonExistingObject cannot be resolved +9 The method nonExistingMethod() is undefined for the type Integer +10 NonExistingClass cannot be resolved to a type +11 The method b2(int, int) in the type ValInvalidParameter is not applicable for the arguments (int) +12 The method a(String) is ambiguous for the type ValInvalidParameter +13 The method a(String) is ambiguous for the type ValInvalidParameter \ No newline at end of file diff --git a/test/transform/resource/messages-idempotent/ValInvalidParameter.java.messages b/test/transform/resource/messages-idempotent/ValInvalidParameter.java.messages new file mode 100644 index 0000000000..539d29cdf8 --- /dev/null +++ b/test/transform/resource/messages-idempotent/ValInvalidParameter.java.messages @@ -0,0 +1,9 @@ +3 cannot find symbol +4 cannot find symbol +5 cannot find symbol +6 cannot find symbol +7 cannot find symbol +8 cannot find symbol +9 method b2 in class ValInvalidParameter cannot be applied to given types; +10 reference to a is ambiguous +11 reference to a is ambiguous \ No newline at end of file diff --git a/test/transform/src/lombok/transform/TestSourceFiles.java b/test/transform/src/lombok/transform/TestSourceFiles.java index ac8b59c100..5fb0614b43 100644 --- a/test/transform/src/lombok/transform/TestSourceFiles.java +++ b/test/transform/src/lombok/transform/TestSourceFiles.java @@ -51,7 +51,7 @@ public File getAfterDirectory() { @Override public File getMessagesDirectory() { - return null; + return new File("test/pretty/resource/messages"); } @Override diff --git a/website/templates/features/GetterSetter.html b/website/templates/features/GetterSetter.html index a429c9acd8..8b16d34d00 100644 --- a/website/templates/features/GetterSetter.html +++ b/website/templates/features/GetterSetter.html @@ -37,6 +37,11 @@ lombok.getter.noIsPrefix = [true | false] (default: false)
If set to true, getters generated for boolean fields will use the get prefix instead of the defaultis prefix, and any generated code that calls getters, such as @ToString, will also use get instead of is +
+ lombok.accessors.capitalization = [basic | beanspec] (default: basic) +
+ Controls how tricky cases like uShaped (one lowercase letter followed by an upper/titlecase letter) are capitalized. basic capitalizes that to getUShaped, and beanspec capitalizes that to getuShaped instead.
+ Both strategies are commonly used in the java ecosystem, though beanspec is more common.
lombok.setter.flagUsage = [warning | error] (default: not set)
diff --git a/website/templates/features/Value.html b/website/templates/features/Value.html index c41b6b102d..e128383f88 100644 --- a/website/templates/features/Value.html +++ b/website/templates/features/Value.html @@ -5,7 +5,7 @@

@Value was introduced as experimental feature in lombok v0.11.4.

- @Value no longer implies @Wither since lombok v0.11.8. + @Value no longer implies @With since lombok v0.11.8.

@Value promoted to the main lombok package since lombok v0.12.0.

diff --git a/website/templates/features/With.html b/website/templates/features/With.html index 8b34f03884..867c17eb9d 100644 --- a/website/templates/features/With.html +++ b/website/templates/features/With.html @@ -27,6 +27,15 @@ <@f.snippets name="With" /> <@f.confKeys> + <>
+ lombok.accessors.prefix += a field prefix (default: empty list) +
+ This is a list property; entries can be added with the += operator. Inherited prefixes from parent config files can be removed with the -= operator. Lombok will strip any matching field prefix from the name of a field in order to determine the name of the getter/setter to generate. For example, if m is one of the prefixes listed in this setting, then a field named mFoobar will result in a getter named getFoobar(), not getMFoobar(). An explicitly configured prefix parameter of an @Accessors annotation takes precedence over this setting. +
+ lombok.accessors.capitalization = [basic | beanspec] (default: basic) +
+ Controls how tricky cases like uShaped (one lowercase letter followed by an upper/titlecase letter) are capitalized. basic capitalizes that to withUShaped, and beanspec capitalizes that to withuShaped instead.
+ Both strategies are commonly used in the java ecosystem, though beanspec is more common.
lombok.with.flagUsage = [warning | error] (default: not set)
diff --git a/website/templates/features/experimental/Accessors.html b/website/templates/features/experimental/Accessors.html index 564ab66d09..9a9385cb91 100644 --- a/website/templates/features/experimental/Accessors.html +++ b/website/templates/features/experimental/Accessors.html @@ -4,9 +4,11 @@ <@f.history>

@Accessors was introduced as experimental feature in lombok v0.11.0. +

+ The lombok.config option lombok.accessors.capitalization = [basic | beanspec] was added in lombok v1.18.24.

- + <@f.experimental>
  • @@ -17,7 +19,6 @@
Current status: neutral - Some changes are expected. These changes are intended to be backwards compatible, but should start in an experimental feature:
    -
  • Open feature request: naming behaviour for properties that start with a lowercase letter followed by an uppercase letter. Half of specs, tools and lombok users prefer that a field named uLimit into getULimit (including lombok) and the other half turn prefer getuLimit. @Accessors may be involved in any update that addresses this request.
  • Open feature request: More control over naming accessors; for example to address creatively named boolean properties: Turn boolean wasRunning into boolean wasRunning() instead of boolean isWasRunning(), as well as more expansive prefix support. @Accessors will be involved if this feature request is addressed.
  • @Accessors currently does not 'cascade' from field @Accessors annotation to the class-level @Accessors annotation, but it does 'cascade' to lombok.config. Changing this is not difficult but backwards incompatible. It's not likely to break much existing code, but this needs to be decided on before the feature can move out of experimental status.
@@ -44,7 +45,7 @@

- The @Accessors annotation is legal on types and fields; the annotation that applies is the one on the field if present, otherwise the one on the class. When a @Accessors annotation on a field is present, any @Accessors annotation also present on the class the field is in, is entirely ignored, even for properties not configured on the field @Accessors. This in contrast to any lombok.config configuration keys which serve as fall-back default if any explicit @Accessors annotation doesn't specify. + The @Accessors annotation is legal on types and fields; the annotation that applies is the one on the field if present, otherwise the one on the class. When an @Accessors annotation on a field is present, any @Accessors annotation also present on the class the field is in, is entirely ignored, even for properties not configured on the field @Accessors. This in contrast to any lombok.config configuration keys which serve as fall-back default if any explicit @Accessors annotation doesn't specify.

@@ -63,6 +64,11 @@ lombok.accessors.prefix += a field prefix (default: empty list)
This is a list property; entries can be added with the += operator. Inherited prefixes from parent config files can be removed with the -= operator. Any class that either doesn't have an @Accessors annotation, or it does, but that annotation does not have an explicit value for the prefix parameter, will act as if @Accessors(prefix = {prefixes listed in configuration}) is present. +
+ lombok.accessors.capitalization = [basic | beanspec] (default: basic) +
+ Controls how tricky cases like uShaped (one lowercase letter followed by an upper/titlecase letter) are capitalized. basic capitalizes that to getUShaped, and beanspec capitalizes that to getuShaped instead.
+ Both strategies are commonly used in the java ecosystem, though beanspec is more common.
lombok.accessors.flagUsage = [warning | error] (default: not set)
diff --git a/website/templates/features/experimental/FieldNameConstants.html b/website/templates/features/experimental/FieldNameConstants.html index e88b76700f..06fa23b5e5 100644 --- a/website/templates/features/experimental/FieldNameConstants.html +++ b/website/templates/features/experimental/FieldNameConstants.html @@ -24,7 +24,7 @@

The @FieldNameConstants annotation generates an inner type which contains 1 constant for each field in your class; either string constants (fields marked public static final, of type java.lang.String) or if you prefer, an enum type with 1 value for each field - write @FieldNameConstants(asEnum = true) for the enum variant. @FieldNameConstants is useful for various marshalling and serialization frameworks. The constant field (whether enum value or string constant) always has the exact same name as the field, capitalization and all, unless you set the lombok.fieldNameConstants.uppercase = true option in your lombok.config file; in that case lombok will try to UPPER_CASE the name.

- The generated inner type is by default called Fields and is public. You can modify this via @FieldNameConstants(innerTypeName = "FieldNames", access = AccessLevel.PACKAGE) for example. The default inner type name can also be modified via configuration key lombok.fieldNameConstants.innerTypeName. The generated fields are always public. + The generated inner type is by default called Fields and is public. You can modify this via @FieldNameConstants(innerTypeName = "FieldNames", level = AccessLevel.PACKAGE) for example. The default inner type name can also be modified via configuration key lombok.fieldNameConstants.innerTypeName. The generated fields are always public.

Must be applied to classes (or enums, though you'd rarely want to do that). By default includes all non-transient, non-static fields. You can use @FieldNameConstants.Include in fields + @FieldNameConstants(onlyExplicitlyIncluded = true), or @FieldNameConstants.Exclude for more fine-grained control.

diff --git a/website/templates/features/val.html b/website/templates/features/val.html index 32a8ffdfba..1b137c6501 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>

diff --git a/website/usageExamples/ValueExample_pre.jpage b/website/usageExamples/ValueExample_pre.jpage index d9550c252a..27b28eb77c 100644 --- a/website/usageExamples/ValueExample_pre.jpage +++ b/website/usageExamples/ValueExample_pre.jpage @@ -1,12 +1,12 @@ import lombok.AccessLevel; import lombok.experimental.NonFinal; import lombok.experimental.Value; -import lombok.experimental.Wither; +import lombok.experimental.With; import lombok.ToString; @Value public class ValueExample { String name; - @Wither(AccessLevel.PACKAGE) @NonFinal int age; + @With(AccessLevel.PACKAGE) @NonFinal int age; double score; protected String[] tags;