diff options
42 files changed, 536 insertions, 82 deletions
diff --git a/.github/ISSUE_TEMPLATE/security_issue.md b/.github/ISSUE_TEMPLATE/security_issue.md deleted file mode 100644 index 44033bc0..00000000 --- a/.github/ISSUE_TEMPLATE/security_issue.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Security issue with lombok -about: Let us know about a security vulnerability in lombok -title: '[DO NOT POST HERE]' -labels: '' -assignees: '' - ---- - -***Please do not report this here!*** - -github issues are public. Please contact us privately so that we can work together to coordinate a fix for the vulnerability together with making the vulnerability public. - -You can inform the [Tidelift security contact](https://tidelift.com/security) or if you prefer, contact the core contributors of Project Lombok directly by emailing `info@projectlombok.org` @@ -7,4 +7,6 @@ Looking for professional support of Project Lombok? Lombok is now part of a tide For a list of all authors, see the AUTHORS file. -For complete project information, see https://projectlombok.org/
\ No newline at end of file +For complete project information, see https://projectlombok.org/ + +You can review our security policy via SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..43745e86 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +#Security Policies and Procedures + +Lombok only runs during compilation and is not required on your servers or in your application's distribution. Nevertheless, the _Project Lombok_ team and community take all security bugs seriously. + +## Reporting a Bug + +To report a security vulnerability, please follow the procedure described in the [Tidelift security policy](https://tidelift.com/docs/security?utm_source=lombok&utm_medium=referral&utm_campaign=github). + +Alternatively, you can send us an email privately via `info@projectlombok.org`. + +## Disclosure Policy + +When we receive a security bug report, it will be assigned a primary handler. This person will coordinate the fix and release process. In case this process requires additional resources beyond the scope of what the core contributors of _Project Lombok_ can reasonably supply, we will inform the Tidelift security team for additional help and coordination. This process will involve the following steps: + +* Inventorize all affected versions along with the platform(s) that lombok runs on which are affected. +* Audit code to find any potential similar problems. +* Prepare fixes for all releases, push these out to all distribution channels including the maven central repo, and put in all due effort to get affected versions marked as affected. + +## Comments on this Policy + +Any comments on this policy or suggestions for improvement can be discussed on [our forum](https://groups.google.com/forum/#!forum/project-lombok), or you can send us an email for any comments or suggestions that contain sensitive information. diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 7f1efb94..849ec3d6 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -3,7 +3,10 @@ Lombok Changelog ### v1.18.9 "Edgy Guinea Pig" * ENHANCEMENT: Thanks to Mark Haynes, the `staticConstructor` will now also be generated if a (private) constructor already exists. [Issue #2100](https://github.com/rzwitserloot/lombok/issues/2100) -* ENHANCEMENT: `val` is now capable of decoding the type of convoluted expressions (particularly if the right hand side involves lambdas and conditional (ternary) expressions). [Pull Request #2109](https://github.com/rzwitserloot/lombok/pull/2109) with thanks to Alexander Bulgakov. +* ENHANCEMENT: `val` is now capable of decoding the type of convoluted expressions (particularly if the right hand side involves lambdas and conditional (ternary) expressions). [Pull Request #2109](https://github.com/rzwitserloot/lombok/pull/2109) and [Pull Request #2138](https://github.com/rzwitserloot/lombok/pull/2138) with thanks to Alexander Bulgakov. +* ENHANCEMENT: You can now configure the generated builder class name via the config system, using key `lombok.builder.className`. See the [Builder documentation](https://projectlombok.org/features/Builder) and [SuperBuilder documentation](https://projectlombok.org/features/experimental/SuperBuilder) +* BUGFIX: Delombok would turn something like `List<byte[]>...` in a method parameter to `List<byte...>...` [Issue #2140](https://github.com/rzwitserloot/lombok/issues/2140) +* BUGFIX: Javac would generate the wrong equals and hashCode if a type-use annotation was put on an array type field [Issue #2165](https://github.com/rzwitserloot/lombok/issues/2165) ### v1.18.8 (May 7th, 2019) * FEATURE: You can now configure `@FieldNameConstants` to `CONSTANT_CASE` the generated constants, using a `lombok.config` option. See the [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants). [Issue #2092](https://github.com/rzwitserloot/lombok/issues/2092). diff --git a/docker/gradle/files/build.gradle b/docker/gradle/files/build.gradle index 49923f04..bbf276c7 100644 --- a/docker/gradle/files/build.gradle +++ b/docker/gradle/files/build.gradle @@ -2,4 +2,5 @@ apply plugin: 'java' dependencies {
compileOnly files('lombok.jar')
+ annotationProcessor files('lombok.jar')
}
\ No newline at end of file diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java index a60af9ee..dfa5ecb5 100644 --- a/src/core/lombok/Builder.java +++ b/src/core/lombok/Builder.java @@ -129,9 +129,9 @@ public @interface Builder { /** * Name of the builder class. * - * Default for {@code @Builder} on types and constructors: {@code (TypeName)Builder}. + * Default for {@code @Builder} on types and constructors: see the configkey {@code lombok.builder.className}, which if not set defaults to {@code (TypeName)Builder}. * <p> - * Default for {@code @Builder} on methods: {@code (ReturnTypeName)Builder}. + * Default for {@code @Builder} on methods: see the configkey {@code lombok.builder.className}, which if not set defaults to {@code (ReturnTypeName)Builder}. * * @return Name of the builder class that will be generated (or if it already exists, will be filled with builder elements). */ diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 84b594f5..975cb72e 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -256,6 +256,13 @@ public class ConfigurationKeys { // ----- Builder ----- /** + * lombok configuration: {@code lombok.builder.classNames} = <String: aJavaIdentifier (optionally with a star as placeholder for the type name)> (Default: {@code *Builder}). + * + * For any usage of the {@code @Builder} annotation without an explicit {@code builderClassName} parameter, this value is used to determine the name of the builder class to generate (or to adapt if such an inner class already exists). + */ + public static final ConfigurationKey<String> BUILDER_CLASS_NAME = new ConfigurationKey<String>("lombok.builder.className", "Default name of the generated builder class. A * is replaced with the name of the relevant type (default = *Builder).") {}; + + /** * lombok configuration: {@code lombok.builder.flagUsage} = {@code WARNING} | {@code ERROR}. * * If set, <em>any</em> usage of {@code @Builder} results in a warning / error. diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 96431a83..aa9d2147 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -209,6 +209,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { List<EclipseNode> nonFinalNonDefaultedFields = null; + if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); + if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder"; + boolean replaceNameInBuilderClassName = builderClassName.contains("*"); + if (parent.get() instanceof TypeDeclaration) { tdParent = parent; TypeDeclaration td = (TypeDeclaration) tdParent.get(); @@ -265,7 +269,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { typeParams = td.typeParameters; thrownExceptions = null; nameOfStaticBuilderMethod = null; - if (builderClassName.isEmpty()) builderClassName = new String(td.name) + "Builder"; + if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(td.name)); + replaceNameInBuilderClassName = false; } else if (parent.get() instanceof ConstructorDeclaration) { ConstructorDeclaration cd = (ConstructorDeclaration) parent.get(); if (cd.typeParameters != null && cd.typeParameters.length > 0) { @@ -279,12 +284,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { typeParams = td.typeParameters; thrownExceptions = cd.thrownExceptions; nameOfStaticBuilderMethod = null; - if (builderClassName.isEmpty()) builderClassName = new String(cd.selector) + "Builder"; + if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(cd.selector)); + replaceNameInBuilderClassName = false; } else if (parent.get() instanceof MethodDeclaration) { MethodDeclaration md = (MethodDeclaration) parent.get(); tdParent = parent.up(); isStatic = md.isStatic(); - + if (toBuilder) { final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type."; char[] token; @@ -360,7 +366,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { typeParams = md.typeParameters; thrownExceptions = md.thrownExceptions; nameOfStaticBuilderMethod = md.selector; - if (builderClassName.isEmpty()) { + if (replaceNameInBuilderClassName) { char[] token; if (md.returnType instanceof QualifiedTypeReference) { char[][] tokens = ((QualifiedTypeReference) md.returnType).tokens; @@ -387,7 +393,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { token = newToken; } - builderClassName = new String(token) + "Builder"; + builderClassName = builderClassName.replace("*", new String(token)); } } else { annotationNode.addError("@Builder is only supported on types, constructors, and methods."); diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 9a86d372..f204bc24 100755 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -203,7 +203,9 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { } // Set the names of the builder classes. - String builderClassName = String.valueOf(td.name) + "Builder"; + String builderClassNameTemplate = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); + if (builderClassNameTemplate == null || builderClassNameTemplate.isEmpty()) builderClassNameTemplate = "*Builder"; + String builderClassName = builderClassNameTemplate.replace("*", String.valueOf(td.name)); String builderImplClassName = builderClassName + "Impl"; typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0]; @@ -228,7 +230,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { if (extendsClause instanceof QualifiedTypeReference) { QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference)extendsClause; String superclassClassName = String.valueOf(qualifiedTypeReference.getLastToken()); - String superclassBuilderClassName = superclassClassName + "Builder"; + String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName); char[][] tokens = Arrays.copyOf(qualifiedTypeReference.tokens, qualifiedTypeReference.tokens.length + 1); tokens[tokens.length] = superclassBuilderClassName.toCharArray(); diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index d758f602..b339c2ca 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -157,6 +157,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { ArrayList<JavacNode> nonFinalNonDefaultedFields = null; + if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); + if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder"; + boolean replaceNameInBuilderClassName = builderClassName.contains("*"); + if (parent.get() instanceof JCClassDecl) { tdParent = parent; JCClassDecl td = (JCClassDecl) tdParent.get(); @@ -211,7 +215,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { typeParams = td.typarams; thrownExceptions = List.nil(); nameOfBuilderMethod = null; - if (builderClassName.isEmpty()) builderClassName = td.name.toString() + "Builder"; + if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString()); + replaceNameInBuilderClassName = false; } else if (fillParametersFrom != null && fillParametersFrom.getName().toString().equals("<init>")) { JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get(); if (!jmd.typarams.isEmpty()) { @@ -225,7 +230,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { typeParams = td.typarams; thrownExceptions = jmd.thrown; nameOfBuilderMethod = null; - if (builderClassName.isEmpty()) builderClassName = td.name.toString() + "Builder"; + if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString()); + replaceNameInBuilderClassName = false; } else if (fillParametersFrom != null) { tdParent = parent.up(); JCClassDecl td = (JCClassDecl) tdParent.get(); @@ -239,9 +245,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (returnType instanceof JCTypeApply) { returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext()); } - if (builderClassName.isEmpty()) { + if (replaceNameInBuilderClassName) { + String replStr = null; if (returnType instanceof JCFieldAccess) { - builderClassName = ((JCFieldAccess) returnType).name.toString() + "Builder"; + replStr = ((JCFieldAccess) returnType).name.toString(); } else if (returnType instanceof JCIdent) { Name n = ((JCIdent) returnType).name; @@ -251,27 +258,30 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return; } } - builderClassName = n.toString() + "Builder"; + replStr = n.toString(); } else if (returnType instanceof JCPrimitiveTypeTree) { - builderClassName = returnType.toString() + "Builder"; - if (Character.isLowerCase(builderClassName.charAt(0))) { - builderClassName = Character.toTitleCase(builderClassName.charAt(0)) + builderClassName.substring(1); + replStr = returnType.toString(); + if (Character.isLowerCase(replStr.charAt(0))) { + replStr = Character.toTitleCase(replStr.charAt(0)) + replStr.substring(1); } } else if (returnType instanceof JCTypeApply) { JCExpression clazz = ((JCTypeApply) returnType).clazz; if (clazz instanceof JCFieldAccess) { - builderClassName = ((JCFieldAccess) clazz).name + "Builder"; + replStr = ((JCFieldAccess) clazz).name.toString(); } else if (clazz instanceof JCIdent) { - builderClassName = ((JCIdent) clazz).name + "Builder"; + replStr = ((JCIdent) clazz).name.toString(); } } - if (builderClassName.isEmpty()) { + if (replStr == null || replStr.isEmpty()) { // This shouldn't happen. System.err.println("Lombok bug ID#20140614-1651: javac HandleBuilder: return type to name conversion failed: " + returnType.getClass()); - builderClassName = td.name.toString() + "Builder"; + replStr = td.name.toString(); } + builderClassName = builderClassName.replace("*", replStr); + replaceNameInBuilderClassName = false; } + if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString()); if (toBuilder) { final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type."; if (returnType instanceof JCArrayTypeTree) { diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index cb12bd4e..e4d7fa7f 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -25,6 +25,7 @@ import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -234,7 +235,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas for (Included<JavacNode, EqualsAndHashCode.Include> member : members) { JavacNode memberNode = member.getNode(); - JCExpression fType = getFieldType(memberNode, fieldAccess); + JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess)); boolean isMethod = memberNode.getKind() == Kind.METHOD; JCExpression fieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess); @@ -279,9 +280,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas break; } } else if (fType instanceof JCArrayTypeTree) { + JCArrayTypeTree array = (JCArrayTypeTree) fType; /* java.util.Arrays.deepHashCode(this.fieldName) //use just hashCode() for primitive arrays. */ - boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree; - boolean primitiveArray = ((JCArrayTypeTree) fType).elemtype instanceof JCPrimitiveTypeTree; + boolean multiDim = unnotate(array.elemtype) instanceof JCArrayTypeTree; + boolean primitiveArray = unnotate(array.elemtype) instanceof JCPrimitiveTypeTree; boolean useDeepHC = multiDim || !primitiveArray; JCExpression hcMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepHC ? "deepHashCode" : "hashCode"); @@ -430,7 +432,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas JavacNode memberNode = member.getNode(); boolean isMethod = memberNode.getKind() == Kind.METHOD; - JCExpression fType = getFieldType(memberNode, fieldAccess); + JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess)); JCExpression thisFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess); JCExpression otherFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode, maker.Ident(otherName)) : createFieldAccessor(maker, memberNode, fieldAccess, maker.Ident(otherName)); if (fType instanceof JCPrimitiveTypeTree) { @@ -450,9 +452,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas break; } } else if (fType instanceof JCArrayTypeTree) { + JCArrayTypeTree array = (JCArrayTypeTree) fType; /* if (!java.util.Arrays.deepEquals(this.fieldName, other.fieldName)) return false; //use equals for primitive arrays. */ - boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree; - boolean primitiveArray = ((JCArrayTypeTree) fType).elemtype instanceof JCPrimitiveTypeTree; + boolean multiDim = unnotate(array.elemtype) instanceof JCArrayTypeTree; + boolean primitiveArray = unnotate(array.elemtype) instanceof JCPrimitiveTypeTree; boolean useDeepEquals = multiDim || !primitiveArray; JCExpression eqMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepEquals ? "deepEquals" : "equals"); @@ -522,4 +525,30 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas public JCStatement returnBool(JavacTreeMaker maker, boolean bool) { return maker.Return(maker.Literal(CTC_BOOLEAN, bool ? 1 : 0)); } + + private boolean jcAnnotatedTypeInit; + private Class<?> jcAnnotatedTypeClass = null; + private Field jcAnnotatedTypeUnderlyingTypeField = null; + + private JCExpression unnotate(JCExpression type) { + if (!isJcAnnotatedType(type)) return type; + if (jcAnnotatedTypeUnderlyingTypeField == null) return type; + try { + return (JCExpression) jcAnnotatedTypeUnderlyingTypeField.get(type); + } catch (Exception ignore) {} + return type; + } + + private boolean isJcAnnotatedType(JCExpression o) { + if (o == null) return false; + if (!jcAnnotatedTypeInit) { + try { + jcAnnotatedTypeClass = Class.forName("com.sun.tools.javac.tree.JCTree$JCAnnotatedType", false, o.getClass().getClassLoader()); + jcAnnotatedTypeUnderlyingTypeField = jcAnnotatedTypeClass.getDeclaredField("underlyingType"); + } + catch (Exception ignore) {} + jcAnnotatedTypeInit = true; + } + return jcAnnotatedTypeClass == o.getClass(); + } } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 0fcaa5f8..9120fa07 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -177,7 +177,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } // Set the names of the builder classes. - String builderClassName = td.name.toString() + "Builder"; + String builderClassNameTemplate = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); + if (builderClassNameTemplate == null || builderClassNameTemplate.isEmpty()) builderClassNameTemplate = "*Builder"; + String builderClassName = builderClassNameTemplate.replace("*", td.name.toString()); String builderImplClassName = builderClassName + "Impl"; JCTree extendsClause = Javac.getExtendsClause(td); JCExpression superclassBuilderClassExpression = null; @@ -189,11 +191,11 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } if (extendsClause instanceof JCFieldAccess) { Name superclassClassName = ((JCFieldAccess)extendsClause).getIdentifier(); - String superclassBuilderClassName = superclassClassName + "Builder"; + String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName); superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess) extendsClause, - tdParent.toName(superclassBuilderClassName)); + tdParent.toName(superclassBuilderClassName)); } else if (extendsClause != null) { - String superclassBuilderClassName = extendsClause.toString() + "Builder"; + String superclassBuilderClassName = builderClassNameTemplate.replace("*", extendsClause.toString()); superclassBuilderClassExpression = chainDots(tdParent, extendsClause.toString(), superclassBuilderClassName); } // If there is no superclass, superclassBuilderClassExpression is still == null at this point. diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java index 3477c51c..1532319f 100644 --- a/src/delombok/lombok/delombok/PrettyPrinter.java +++ b/src/delombok/lombok/delombok/PrettyPrinter.java @@ -692,7 +692,10 @@ public class PrettyPrinter extends JCTree.Visitor { @Override public void visitTypeApply(JCTypeApply tree) { print(tree.clazz); print("<"); + boolean temp = innermostArrayBracketsAreVarargs; + innermostArrayBracketsAreVarargs = false; print(tree.arguments, ", "); + innermostArrayBracketsAreVarargs = temp; print(">"); } diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java index c0c2cea6..0c66bb31 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java @@ -21,19 +21,27 @@ */ package lombok.eclipse.agent; +import lombok.permit.Permit; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; +import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression; 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.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.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; @@ -45,12 +53,12 @@ import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; - -import lombok.permit.Permit; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; 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 org.eclipse.jdt.core.compiler.CategorizedProblem.CAT_TYPE; @@ -358,6 +366,10 @@ public class PatchVal { } private static TypeBinding resolveForExpression(Expression collection, BlockScope scope) { + CompilationUnitDeclaration referenceContext = scope.compilationUnitScope().referenceContext; + ProblemReporter oldProblemReporter = referenceContext.problemReporter; + referenceContext.problemReporter = new ProblemReporter(DefaultErrorHandlingPolicies.exitOnFirstError(), + oldProblemReporter.options, oldProblemReporter.problemFactory); try { return collection.resolveType(scope); } catch (ArrayIndexOutOfBoundsException e) { @@ -384,11 +396,76 @@ public class PatchVal { } } 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; + } finally { + referenceContext.problemReporter = oldProblemReporter; + } + } + + private static void clearIgnoreFurtherInvestigationField(ReferenceContext currentContext) { + if (currentContext instanceof AbstractMethodDeclaration) { + AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) currentContext; + methodDeclaration.ignoreFurtherInvestigation = false; + } else if (currentContext instanceof LambdaExpression) { + LambdaExpression lambdaExpression = (LambdaExpression) currentContext; + setValue(getField(LambdaExpression.class, "ignoreFurtherInvestigation"), lambdaExpression, false); + + Scope parent = lambdaExpression.enclosingScope.parent; + while (parent != null) { + switch(parent.kind) { + case Scope.CLASS_SCOPE: + case Scope.METHOD_SCOPE: + ReferenceContext parentAST = parent.referenceContext(); + if (parentAST != lambdaExpression) { + clearIgnoreFurtherInvestigationField(parentAST); + return; + } + default: + parent = parent.parent; + break; + } + } + + } else if (currentContext instanceof TypeDeclaration) { + TypeDeclaration typeDeclaration = (TypeDeclaration) currentContext; + typeDeclaration.ignoreFurtherInvestigation = false; + } else if (currentContext instanceof CompilationUnitDeclaration) { + CompilationUnitDeclaration typeDeclaration = (CompilationUnitDeclaration) currentContext; + typeDeclaration.ignoreFurtherInvestigation = false; + } else { + throw new UnsupportedOperationException("clearIgnoreFurtherInvestigationField for " + currentContext.getClass()); + } + } + + private static void setValue(Field field, Object object, Object value) { + try { + field.set(object, value); + } catch (IllegalAccessException e) { + throw sneakyThrow(e); + } + } + + private static Field getField(Class clazz, String name) { + try { + return Permit.getField(clazz, name); + } catch (NoSuchFieldException e) { + throw sneakyThrow(e); } } } diff --git a/test/pretty/resource/after/ArrayAndVarargs.java b/test/pretty/resource/after/ArrayAndVarargs.java new file mode 100644 index 00000000..9727bff6 --- /dev/null +++ b/test/pretty/resource/after/ArrayAndVarargs.java @@ -0,0 +1,7 @@ +import java.util.List; +class ArrayAndVarargs { + void test(List<String[]>... foo) { + } + void test2(byte[]... foo) { + } +} diff --git a/test/pretty/resource/before/ArrayAndVarargs.java b/test/pretty/resource/before/ArrayAndVarargs.java new file mode 100644 index 00000000..38c9b276 --- /dev/null +++ b/test/pretty/resource/before/ArrayAndVarargs.java @@ -0,0 +1,9 @@ +import java.util.List; + +class ArrayAndVarargs { + void test(List<String[]>... foo) { + } + + void test2(byte[]... foo) { + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/BuilderComplex.java b/test/transform/resource/after-delombok/BuilderComplex.java index a89d7114..c63d7b59 100644 --- a/test/transform/resource/after-delombok/BuilderComplex.java +++ b/test/transform/resource/after-delombok/BuilderComplex.java @@ -3,7 +3,7 @@ class BuilderComplex { private static <T extends Number> void testVoidWithGenerics(T number, int arg2, String arg3, BuilderComplex selfRef) { } @java.lang.SuppressWarnings("all") - public static class VoidBuilder<T extends Number> { + public static class TestVoidName<T extends Number> { @java.lang.SuppressWarnings("all") private T number; @java.lang.SuppressWarnings("all") @@ -13,25 +13,25 @@ class BuilderComplex { @java.lang.SuppressWarnings("all") private BuilderComplex selfRef; @java.lang.SuppressWarnings("all") - VoidBuilder() { + TestVoidName() { } @java.lang.SuppressWarnings("all") - public VoidBuilder<T> number(final T number) { + public TestVoidName<T> number(final T number) { this.number = number; return this; } @java.lang.SuppressWarnings("all") - public VoidBuilder<T> arg2(final int arg2) { + public TestVoidName<T> arg2(final int arg2) { this.arg2 = arg2; return this; } @java.lang.SuppressWarnings("all") - public VoidBuilder<T> arg3(final String arg3) { + public TestVoidName<T> arg3(final String arg3) { this.arg3 = arg3; return this; } @java.lang.SuppressWarnings("all") - public VoidBuilder<T> selfRef(final BuilderComplex selfRef) { + public TestVoidName<T> selfRef(final BuilderComplex selfRef) { this.selfRef = selfRef; return this; } @@ -42,11 +42,11 @@ class BuilderComplex { @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { - return "BuilderComplex.VoidBuilder(number=" + this.number + ", arg2=" + this.arg2 + ", arg3=" + this.arg3 + ", selfRef=" + this.selfRef + ")"; + return "BuilderComplex.TestVoidName(number=" + this.number + ", arg2=" + this.arg2 + ", arg3=" + this.arg3 + ", selfRef=" + this.selfRef + ")"; } } @java.lang.SuppressWarnings("all") - public static <T extends Number> VoidBuilder<T> builder() { - return new VoidBuilder<T>(); + public static <T extends Number> TestVoidName<T> builder() { + return new TestVoidName<T>(); } } diff --git a/test/transform/resource/after-delombok/BuilderCustomName.java b/test/transform/resource/after-delombok/BuilderCustomName.java new file mode 100644 index 00000000..4db08220 --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderCustomName.java @@ -0,0 +1,47 @@ +import java.util.List; +class BuilderCustomName<T> { + private final int field; + @java.lang.SuppressWarnings("all") + public static abstract class SimpleTestBuilder<T, C extends BuilderCustomName<T>, B extends SimpleTestBuilder<T, C, B>> { + @java.lang.SuppressWarnings("all") + private int field; + @java.lang.SuppressWarnings("all") + protected abstract B self(); + @java.lang.SuppressWarnings("all") + public abstract C build(); + @java.lang.SuppressWarnings("all") + public B field(final int field) { + this.field = field; + return self(); + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderCustomName.SimpleTestBuilder(field=" + this.field + ")"; + } + } + @java.lang.SuppressWarnings("all") + private static final class SimpleTestBuilderImpl<T> extends SimpleTestBuilder<T, BuilderCustomName<T>, SimpleTestBuilderImpl<T>> { + @java.lang.SuppressWarnings("all") + private SimpleTestBuilderImpl() { + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + protected SimpleTestBuilderImpl<T> self() { + return this; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public BuilderCustomName<T> build() { + return new BuilderCustomName<T>(this); + } + } + @java.lang.SuppressWarnings("all") + protected BuilderCustomName(final SimpleTestBuilder<T, ?, ?> b) { + this.field = b.field; + } + @java.lang.SuppressWarnings("all") + public static <T> SimpleTestBuilder<T, ?, ?> builder() { + return new SimpleTestBuilderImpl<T>(); + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeAnnotated.java b/test/transform/resource/after-delombok/EqualsAndHashCodeAnnotated.java new file mode 100644 index 00000000..64b6f4d3 --- /dev/null +++ b/test/transform/resource/after-delombok/EqualsAndHashCodeAnnotated.java @@ -0,0 +1,51 @@ +import java.lang.annotation.*; + +class EqualsAndHashCodeAnnotated { + @Annotated + int primitive; + @Annotated + Object object; + int @Annotated [] primitiveValues; + int @Annotated [] @Annotated [] morePrimitiveValues; + Integer @Annotated [] objectValues; + Integer @Annotated [] @Annotated [] moreObjectValues; + @Target(ElementType.TYPE_USE) + @Retention(RetentionPolicy.SOURCE) + @interface Annotated { + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof EqualsAndHashCodeAnnotated)) return false; + final EqualsAndHashCodeAnnotated other = (EqualsAndHashCodeAnnotated) o; + if (!other.canEqual((java.lang.Object) this)) return false; + if (this.primitive != other.primitive) return false; + final java.lang.Object this$object = this.object; + final java.lang.Object other$object = other.object; + if (this$object == null ? other$object != null : !this$object.equals(other$object)) return false; + if (!java.util.Arrays.equals(this.primitiveValues, other.primitiveValues)) return false; + if (!java.util.Arrays.deepEquals(this.morePrimitiveValues, other.morePrimitiveValues)) return false; + if (!java.util.Arrays.deepEquals(this.objectValues, other.objectValues)) return false; + if (!java.util.Arrays.deepEquals(this.moreObjectValues, other.moreObjectValues)) return false; + return true; + } + @java.lang.SuppressWarnings("all") + protected boolean canEqual(final java.lang.Object other) { + return other instanceof EqualsAndHashCodeAnnotated; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.primitive; + final java.lang.Object $object = this.object; + result = result * PRIME + ($object == null ? 43 : $object.hashCode()); + result = result * PRIME + java.util.Arrays.hashCode(this.primitiveValues); + result = result * PRIME + java.util.Arrays.deepHashCode(this.morePrimitiveValues); + result = result * PRIME + java.util.Arrays.deepHashCode(this.objectValues); + result = result * PRIME + java.util.Arrays.deepHashCode(this.moreObjectValues); + return result; + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/ValInLambda.java b/test/transform/resource/after-delombok/ValInLambda.java index 7ce1e1b4..861fb9da 100644 --- a/test/transform/resource/after-delombok/ValInLambda.java +++ b/test/transform/resource/after-delombok/ValInLambda.java @@ -2,17 +2,26 @@ class ValInLambda { Runnable foo = (Runnable) () -> { final int i = 1; + final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable) () -> { + } : System.out::println; }; - + public void easyLambda() { Runnable foo = (Runnable) () -> { final int i = 1; }; } - + public void easyIntersectionLambda() { Runnable foo = (Runnable) () -> { final int i = 1; }; } + + public void easyLubLambda() { + Runnable foo = (Runnable) () -> { + final java.lang.Runnable fooInner = (System.currentTimeMillis() > 0) ? (Runnable) () -> { + } : System.out::println; + }; + } } diff --git a/test/transform/resource/after-delombok/ValLambda.java b/test/transform/resource/after-delombok/ValLambda.java index 00ff27ad..24ae3b5f 100644 --- a/test/transform/resource/after-delombok/ValLambda.java +++ b/test/transform/resource/after-delombok/ValLambda.java @@ -1,15 +1,27 @@ // version 8: class ValLambda { + static { + final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable) () -> { + } : System.out::println; + } + + { + final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable) () -> { + } : System.out::println; + } + public void easyLambda() { final java.lang.Runnable foo = (Runnable) () -> { }; } + public void easyIntersectionLambda() { final java.lang.Runnable foo = (Runnable & java.io.Serializable) () -> { }; final java.io.Serializable bar = (java.io.Serializable & Runnable) () -> { }; } + public void easyLubLambda() { final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable) () -> { } : System.out::println; diff --git a/test/transform/resource/after-ecj/BuilderComplex.java b/test/transform/resource/after-ecj/BuilderComplex.java index 93d70fe9..23dbf058 100644 --- a/test/transform/resource/after-ecj/BuilderComplex.java +++ b/test/transform/resource/after-ecj/BuilderComplex.java @@ -1,27 +1,27 @@ import java.util.List; import lombok.Builder; class BuilderComplex { - public static @java.lang.SuppressWarnings("all") class VoidBuilder<T extends Number> { + public static @java.lang.SuppressWarnings("all") class TestVoidName<T extends Number> { private @java.lang.SuppressWarnings("all") T number; private @java.lang.SuppressWarnings("all") int arg2; private @java.lang.SuppressWarnings("all") String arg3; private @java.lang.SuppressWarnings("all") BuilderComplex selfRef; - @java.lang.SuppressWarnings("all") VoidBuilder() { + @java.lang.SuppressWarnings("all") TestVoidName() { super(); } - public @java.lang.SuppressWarnings("all") VoidBuilder<T> number(final T number) { + public @java.lang.SuppressWarnings("all") TestVoidName<T> number(final T number) { this.number = number; return this; } - public @java.lang.SuppressWarnings("all") VoidBuilder<T> arg2(final int arg2) { + public @java.lang.SuppressWarnings("all") TestVoidName<T> arg2(final int arg2) { this.arg2 = arg2; return this; } - public @java.lang.SuppressWarnings("all") VoidBuilder<T> arg3(final String arg3) { + public @java.lang.SuppressWarnings("all") TestVoidName<T> arg3(final String arg3) { this.arg3 = arg3; return this; } - public @java.lang.SuppressWarnings("all") VoidBuilder<T> selfRef(final BuilderComplex selfRef) { + public @java.lang.SuppressWarnings("all") TestVoidName<T> selfRef(final BuilderComplex selfRef) { this.selfRef = selfRef; return this; } @@ -29,7 +29,7 @@ class BuilderComplex { BuilderComplex.<T>testVoidWithGenerics(number, arg2, arg3, selfRef); } public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { - return (((((((("BuilderComplex.VoidBuilder(number=" + this.number) + ", arg2=") + this.arg2) + ", arg3=") + this.arg3) + ", selfRef=") + this.selfRef) + ")"); + return (((((((("BuilderComplex.TestVoidName(number=" + this.number) + ", arg2=") + this.arg2) + ", arg3=") + this.arg3) + ", selfRef=") + this.selfRef) + ")"); } } BuilderComplex() { @@ -37,7 +37,7 @@ class BuilderComplex { } private static @Builder(buildMethodName = "execute") <T extends Number>void testVoidWithGenerics(T number, int arg2, String arg3, BuilderComplex selfRef) { } - public static @java.lang.SuppressWarnings("all") <T extends Number>VoidBuilder<T> builder() { - return new VoidBuilder<T>(); + public static @java.lang.SuppressWarnings("all") <T extends Number>TestVoidName<T> builder() { + return new TestVoidName<T>(); } } diff --git a/test/transform/resource/after-ecj/BuilderCustomName.java b/test/transform/resource/after-ecj/BuilderCustomName.java new file mode 100644 index 00000000..1067a9d1 --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderCustomName.java @@ -0,0 +1,37 @@ +import java.util.List; +@lombok.experimental.SuperBuilder class BuilderCustomName<T> { + public static abstract @java.lang.SuppressWarnings("all") class SimpleTestBuilder<T, C extends BuilderCustomName<T>, B extends SimpleTestBuilder<T, C, B>> { + private @java.lang.SuppressWarnings("all") int field; + public SimpleTestBuilder() { + super(); + } + protected abstract @java.lang.SuppressWarnings("all") B self(); + public abstract @java.lang.SuppressWarnings("all") C build(); + public @java.lang.SuppressWarnings("all") B field(final int field) { + this.field = field; + return self(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("BuilderCustomName.SimpleTestBuilder(field=" + this.field) + ")"); + } + } + private static final @java.lang.SuppressWarnings("all") class SimpleTestBuilderImpl<T> extends SimpleTestBuilder<T, BuilderCustomName<T>, SimpleTestBuilderImpl<T>> { + private SimpleTestBuilderImpl() { + super(); + } + protected @java.lang.Override @java.lang.SuppressWarnings("all") SimpleTestBuilderImpl<T> self() { + return this; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") BuilderCustomName<T> build() { + return new BuilderCustomName<T>(this); + } + } + private final int field; + protected @java.lang.SuppressWarnings("all") BuilderCustomName(final SimpleTestBuilder<T, ?, ?> b) { + super(); + this.field = b.field; + } + public static @java.lang.SuppressWarnings("all") <T>SimpleTestBuilder<T, ?, ?> builder() { + return new SimpleTestBuilderImpl<T>(); + } +} diff --git a/test/transform/resource/after-ecj/ValInLambda.java b/test/transform/resource/after-ecj/ValInLambda.java index 7669789b..0fac61e9 100644 --- a/test/transform/resource/after-ecj/ValInLambda.java +++ b/test/transform/resource/after-ecj/ValInLambda.java @@ -1,9 +1,9 @@ -// version 8: - import lombok.val; class ValInLambda { Runnable foo = (Runnable) () -> { final @val int i = 1; + final @lombok.val java.lang.Runnable foo = ((System.currentTimeMillis() > 0) ? (Runnable) () -> { +} : System.out::println); }; ValInLambda() { super(); @@ -18,4 +18,10 @@ class ValInLambda { final @val int i = 1; }; } + public void easyLubLambda() { + Runnable foo = (Runnable) () -> { + final @lombok.val java.lang.Runnable fooInner = ((System.currentTimeMillis() > 0) ? (Runnable) () -> { +} : System.out::println); +}; + } } diff --git a/test/transform/resource/after-ecj/ValLambda.java b/test/transform/resource/after-ecj/ValLambda.java index fcb855b3..5b52869f 100644 --- a/test/transform/resource/after-ecj/ValLambda.java +++ b/test/transform/resource/after-ecj/ValLambda.java @@ -1,4 +1,14 @@ class ValLambda { + static { + final @lombok.val java.lang.Runnable foo = ((System.currentTimeMillis() > 0) ? (Runnable) () -> { +} : System.out::println); + } + { + final @lombok.val java.lang.Runnable foo = ((System.currentTimeMillis() > 0) ? (Runnable) () -> { +} : System.out::println); + } + <clinit>() { + } ValLambda() { super(); } diff --git a/test/transform/resource/before/BuilderComplex.java b/test/transform/resource/before/BuilderComplex.java index c13f5877..46f62721 100644 --- a/test/transform/resource/before/BuilderComplex.java +++ b/test/transform/resource/before/BuilderComplex.java @@ -1,3 +1,4 @@ +//CONF: lombok.builder.className = Test*Name import java.util.List; import lombok.Builder; diff --git a/test/transform/resource/before/BuilderCustomName.java b/test/transform/resource/before/BuilderCustomName.java new file mode 100644 index 00000000..d5709e63 --- /dev/null +++ b/test/transform/resource/before/BuilderCustomName.java @@ -0,0 +1,7 @@ +//CONF: lombok.builder.className = SimpleTestBuilder +import java.util.List; + +@lombok.experimental.SuperBuilder +class BuilderCustomName<T> { + private final int field; +} diff --git a/test/transform/resource/before/BuilderJavadoc.java b/test/transform/resource/before/BuilderJavadoc.java index c2e0a6e0..390e2096 100644 --- a/test/transform/resource/before/BuilderJavadoc.java +++ b/test/transform/resource/before/BuilderJavadoc.java @@ -4,7 +4,7 @@ import java.util.List; class BuilderJavadoc<T> { /** * basic gets only a builder setter. - * @see #getsetwith + * @see #getsetwith * @param tag is moved to the setter. * @return tag is removed from the setter. */ @@ -49,6 +49,5 @@ class BuilderJavadoc<T> { this.predefWithJavadoc = x * 100; return this; } - } - + } } diff --git a/test/transform/resource/before/EqualsAndHashCodeAnnotated.java b/test/transform/resource/before/EqualsAndHashCodeAnnotated.java new file mode 100644 index 00000000..d672b982 --- /dev/null +++ b/test/transform/resource/before/EqualsAndHashCodeAnnotated.java @@ -0,0 +1,19 @@ +//version 8 +import java.lang.annotation.*; + +@lombok.EqualsAndHashCode +class EqualsAndHashCodeAnnotated { + @Annotated int primitive; + @Annotated Object object; + + int @Annotated [] primitiveValues; + int @Annotated [] @Annotated [] morePrimitiveValues; + + Integer @Annotated [] objectValues; + Integer @Annotated [] @Annotated [] moreObjectValues; + + @Target(ElementType.TYPE_USE) + @Retention(RetentionPolicy.SOURCE) + @interface Annotated { + } +} diff --git a/test/transform/resource/before/ValInLambda.java b/test/transform/resource/before/ValInLambda.java index 2c2a5942..a5364f8e 100644 --- a/test/transform/resource/before/ValInLambda.java +++ b/test/transform/resource/before/ValInLambda.java @@ -5,6 +5,7 @@ import lombok.val; class ValInLambda { Runnable foo = (Runnable) () -> { val i = 1; + lombok.val foo = (System.currentTimeMillis() > 0) ? (Runnable)()-> {} : System.out::println; }; public void easyLambda() { @@ -18,4 +19,10 @@ class ValInLambda { val i = 1; }; } + + public void easyLubLambda() { + Runnable foo = (Runnable) () -> { + lombok.val fooInner = (System.currentTimeMillis() > 0) ? (Runnable)()-> {} : System.out::println; + }; + } } diff --git a/test/transform/resource/before/ValLambda.java b/test/transform/resource/before/ValLambda.java index 35f83c3c..5c9c4a43 100644 --- a/test/transform/resource/before/ValLambda.java +++ b/test/transform/resource/before/ValLambda.java @@ -1,5 +1,13 @@ // version 8: class ValLambda { + + static { + lombok.val foo = (System.currentTimeMillis() > 0) ? (Runnable)()-> {} : System.out::println; + } + { + lombok.val foo = (System.currentTimeMillis() > 0) ? (Runnable)()-> {} : System.out::println; + } + public void easyLambda() { lombok.val foo = (Runnable)()-> {}; } diff --git a/test/transform/resource/messages-ecj/ValLambda.java.messages b/test/transform/resource/messages-ecj/ValLambda.java.messages index 21c831c3..e6940434 100644 --- a/test/transform/resource/messages-ecj/ValLambda.java.messages +++ b/test/transform/resource/messages-ecj/ValLambda.java.messages @@ -1,2 +1,2 @@ -14 Function is a raw type. References to generic type Function<T,R> should be parameterized -15 Function is a raw type. References to generic type Function<T,R> should be parameterized
\ No newline at end of file +23 Function is a raw type. References to generic type Function<T,R> should be parameterized +24 Function is a raw type. References to generic type Function<T,R> should be parameterized
\ No newline at end of file diff --git a/website/resources/css/custom.css b/website/resources/css/custom.css index 0166b84e..bd838df5 100644 --- a/website/resources/css/custom.css +++ b/website/resources/css/custom.css @@ -14,7 +14,7 @@ background-position: 6px; background-size: 12px; padding: 2px 8px 2px 26px; - color: #FFF; + color: white; } .tidelift-link { @@ -22,7 +22,7 @@ border-top-left-radius: 18px; background-color: #626980; box-sizing: border-box; - color: #FFF; + color: white; display: flex; top: 46px; right: 0px; @@ -59,6 +59,36 @@ pre { text-align: left; } +.tideliftb { + border-radius: 4px; + border: 2px solid #D9230F; + font-size: 28px; + width: 330px; + line-height: 48px; + display: inline-block; + margin: 16px 0; + text-align: center; +} + +.tideliftb1 { + background-color: white; + float: left; + color: #D9230F; +} + +.tideliftb1:hover { + color: #D9230F; +} + +.tideliftb2 { + background-color: #D9230F; + color: #FCFCFC; +} + +.tideliftb2:hover { + color: #FCFCFC; +} + .buttonLike { cursor: pointer; background: -webkit-linear-gradient(top, #FFFEF7, #CFCEC7); @@ -88,6 +118,10 @@ pre { margin-top: 20px; } +.tidelift { + font-size: 16px; +} + .formErr { color: #FF7777; } diff --git a/website/resources/img/projectlombok-tidelift-mix-orig.png b/website/resources/img/projectlombok-tidelift-mix-orig.png Binary files differnew file mode 100644 index 00000000..c3521b35 --- /dev/null +++ b/website/resources/img/projectlombok-tidelift-mix-orig.png diff --git a/website/resources/img/projectlombok-tidelift-mix.png b/website/resources/img/projectlombok-tidelift-mix.png Binary files differnew file mode 100644 index 00000000..082570d3 --- /dev/null +++ b/website/resources/img/projectlombok-tidelift-mix.png diff --git a/website/templates/features/Builder.html b/website/templates/features/Builder.html index 4fe416ee..af1ffd3a 100644 --- a/website/templates/features/Builder.html +++ b/website/templates/features/Builder.html @@ -160,6 +160,10 @@ public class JacksonExample { <@f.confKeys> <dt> + <code>lombok.builder.className</code> = [a java identifier with an optional star to indicate where the return type name goes] (default: <code>*Builder</code>) + </dt><dd> + Unless you explicitly pick the builder's class name with the <code>builderClassName</code> parameter, this name is chosen; any star in the name is replaced with the relevant return type. + </dd><dt> <code>lombok.builder.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set) </dt><dd> Lombok will flag any usage of <code>@Builder</code> as a warning or error if configured. diff --git a/website/templates/features/_features.html b/website/templates/features/_features.html index 0b93f88e..f54a8fca 100644 --- a/website/templates/features/_features.html +++ b/website/templates/features/_features.html @@ -65,7 +65,7 @@ <#macro scaffold title logline load=[]> <@main.scaffold load title> - <a class="tidelift-link" href="https://tidelift.com/subscription/pkg/maven-org-projectlombok-lombok?utm_source=lombok&utm_medium=referral&utm_campaign=docs">Get Professionally Supported Lombok</a> + <a class="tidelift-link" href="/tidelift">Get Lombok for Enterprise</a> <div class="page-header top5" id="featureContent"> <div class="row text-center"> <div class="header-group"> diff --git a/website/templates/features/experimental/SuperBuilder.html b/website/templates/features/experimental/SuperBuilder.html index c68e28ca..5676b60c 100644 --- a/website/templates/features/experimental/SuperBuilder.html +++ b/website/templates/features/experimental/SuperBuilder.html @@ -52,6 +52,10 @@ <@f.confKeys> <dt> + <code>lombok.builder.className</code> = [a java identifier with an optional star to indicate where the return type name goes] (default: <code>*Builder</code>) + </dt><dd> + This is the name of the generated builder class; any star in the name is replaced with the relevant return type. Note that the parent class must also have the same setting (the entire type hierarchy annoated with <code>@SuperBuilder</code> needs the same setting). + </dd><dt> <code>lombok.superBuilder.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set) </dt><dd> Lombok will flag any usage of <code>@SuperBuilder</code> as a warning or error if configured. diff --git a/website/templates/features/experimental/index.html b/website/templates/features/experimental/index.html index 29dcd146..112d30c4 100644 --- a/website/templates/features/experimental/index.html +++ b/website/templates/features/experimental/index.html @@ -2,7 +2,7 @@ <#import "../_features.html" as f> <@main.scaffold title="Experimental"> - <a class="tidelift-link" href="https://tidelift.com/subscription/pkg/maven-org-projectlombok-lombok?utm_source=lombok&utm_medium=referral&utm_campaign=docs">Get Professionally Supported Lombok</a> + <a class="tidelift-link" href="/tidelift">Get Lombok for Enterprise</a> <div class="page-header top5"> <div class="row text-center"> <@main.h1 title="Lombok experimental features" /> diff --git a/website/templates/features/index.html b/website/templates/features/index.html index bd7cb00c..06b47c0b 100644 --- a/website/templates/features/index.html +++ b/website/templates/features/index.html @@ -1,7 +1,7 @@ <#import "../_scaffold.html" as main> <@main.scaffold title="Stable"> - <a class="tidelift-link" href="https://tidelift.com/subscription/pkg/maven-org-projectlombok-lombok?utm_source=lombok&utm_medium=referral&utm_campaign=docs">Get Professionally Supported Lombok</a> + <a class="tidelift-link" href="/tidelift">Get Lombok for Enterprise</a> <div class="page-header top5"> <div class="row text-center"> <@main.h1 title="Lombok features" /> diff --git a/website/templates/main.html b/website/templates/main.html index 75f5b9e8..be8a3bd9 100644 --- a/website/templates/main.html +++ b/website/templates/main.html @@ -1,6 +1,6 @@ <#import "/_scaffold.html" as main> <@main.scaffold load=["/js/supporters.js"]> - <a class="tidelift-link" href="https://tidelift.com/subscription/pkg/maven-org-projectlombok-lombok?utm_source=lombok&utm_medium=referral&utm_campaign=homepage">Get Professionally Supported Lombok</a> + <a class="tidelift-link" href="/tidelift">Get Lombok for Enterprise</a> <div class="page-header top5"> <div class="row text-center"> <@main.h1 title="Project Lombok" /> diff --git a/website/templates/tidelift.html b/website/templates/tidelift.html new file mode 100644 index 00000000..7f0ab88b --- /dev/null +++ b/website/templates/tidelift.html @@ -0,0 +1,34 @@ +<#import "/_scaffold.html" as main> + +<@main.scaffold title="Project Lombok for Enterprise"> + <div class="page-header top5 tidelift"> + <div class="row text-center"> + <h2>Available as part of the Tidelift Subscription</h2> + </div> + <div class="row"> + <img src="/img/projectlombok-tidelift-mix.png" width="200" height="150" class="pull-right" alt="tidelift+lombok" /> + <p> + Project Lombok and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. + </p><p> + If you want the flexibility of open source and the confidence of commercial-grade software, this is for you. + </p> + </div> + <div class="row text-center"> + <a class="tideliftb tideliftb1" href="https://tidelift.com/subscription/pkg/maven-org-projectlombok-lombok?utm_source=lombok&utm_medium=referral&utm_campaign=enterprise">LEARN MORE</a> <a class="tideliftb tideliftb2" href="https://tidelift.com/subscription/request-a-demo?utm_source=lombok&utm_medium=referral&utm_campaign=enterprise">REQUEST A DEMO</a> + </div> + <div class="row text-center"> + <h2>The Tidelift Subscription manages your dependencies for you</h2> + </div> + <div class="row"> + <p> + <ul> + <li>Get the tools you need to continuously catalog and understand the open source software that your application depends on.</li> + <li>Your subscription helps pay the open source maintainers of the exact packages you use to ensure they meet the standards you require.</li> + <li>Address issues proactively, with tools that scan for new security, licensing, and maintenance issues, and alert our participating open source maintainers so they can resolve them on your behalf.</li> + <li>Measure and improve your open source dependencies' health—which improves your app’s health—and get a short list of high-impact steps your team can take to improve them even more.</li> + <li>Get commercial assurances that don't come for free with open source packages, like intellectual property indemnification and support under a service level agreement. You expect these guarantees from proprietary software, and you can have them when using open source as well.</li> + </ul> + The end result? All of the capabilities you expect from commercial-grade software, for the full breadth of open source you use. That means less time grappling with esoteric open source trivia, and more time building your own applications—and your business. + </div> + </div> +</@main.scaffold> |