diff options
Diffstat (limited to 'src/core')
25 files changed, 374 insertions, 149 deletions
diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java index af3c3c06..a16717cc 100644 --- a/src/core/lombok/Builder.java +++ b/src/core/lombok/Builder.java @@ -48,7 +48,7 @@ import java.lang.annotation.Target; * as the relevant class, unless a method has been annotated, in which case it'll be equal to the * return type of that method. * <p> - * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Builder">the project lombok features page for @Builder</a>. + * Complete documentation is found at <a href="https://projectlombok.org/features/Builder">the project lombok features page for @Builder</a>. * <br> * <p> * Before: diff --git a/src/core/lombok/Cleanup.java b/src/core/lombok/Cleanup.java index 528855cd..a3a1c198 100644 --- a/src/core/lombok/Cleanup.java +++ b/src/core/lombok/Cleanup.java @@ -61,10 +61,10 @@ import java.lang.annotation.Target; * outStream.write(b, 0, r); * } * } finally { - * if (out != null) out.close(); + * if (outStream != null) outStream.close(); * } * } finally { - * if (in != null) in.close(); + * if (inStream != null) inStream.close(); * } * } * </pre> diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 90621027..4ea3b91a 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -41,19 +41,23 @@ public class ConfigurationKeys { /** * lombok configuration: {@code lombok.addGeneratedAnnotation} = {@code true} | {@code false}. * - * If unset or {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated, unless {@code lombok.addJavaxGeneratedAnnotation} is set. + * If {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated, unless {@code lombok.addJavaxGeneratedAnnotation} is set. + * <br /> + * <em>BREAKING CHANGE</em>: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9. * * @see ConfigurationKeys#ADD_JAVAX_GENERATED_ANNOTATIONS * @see ConfigurationKeys#ADD_LOMBOK_GENERATED_ANNOTATIONS * @deprecated Since version 1.16.14, use {@link #ADD_JAVAX_GENERATED_ANNOTATIONS} instead. */ @Deprecated - public static final ConfigurationKey<Boolean> ADD_GENERATED_ANNOTATIONS = new ConfigurationKey<Boolean>("lombok.addGeneratedAnnotation", "Generate @javax.annotation.Generated on all generated code (default: true). Deprecated, use 'lombok.addJavaxGeneratedAnnotation' instead.") {}; + public static final ConfigurationKey<Boolean> ADD_GENERATED_ANNOTATIONS = new ConfigurationKey<Boolean>("lombok.addGeneratedAnnotation", "Generate @javax.annotation.Generated on all generated code (default: false). Deprecated, use 'lombok.addJavaxGeneratedAnnotation' instead.") {}; /** * lombok configuration: {@code lombok.addJavaxGeneratedAnnotation} = {@code true} | {@code false}. * - * If unset or {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated, unless {@code lombok.addGeneratedAnnotation} is set to {@code false}. + * If {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated. + * <br /> + * <em>BREAKING CHANGE</em>: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9. */ public static final ConfigurationKey<Boolean> ADD_JAVAX_GENERATED_ANNOTATIONS = new ConfigurationKey<Boolean>("lombok.addJavaxGeneratedAnnotation", "Generate @javax.annotation.Generated on all generated code (default: follow lombok.addGeneratedAnnotation).") {}; @@ -89,10 +93,25 @@ public class ConfigurationKeys { * To suppress the generation of it, set this configuration to {@code true}. * * NB: GWT projects, and probably android projects, should explicitly set this key to {@code true} for the entire project. + * + * <br /> + * <em>BREAKING CHANGE</em>: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as {@code @ConstructorProperties} requires extra modules in JDK9. + * + * @see ConfigurationKeys#ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES + * @deprecated Since version 2.0, use {@link #ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES} instead. */ + @Deprecated public static final ConfigurationKey<Boolean> ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES = new ConfigurationKey<Boolean>("lombok.anyConstructor.suppressConstructorProperties", "Suppress the generation of @ConstructorProperties for generated constructors (default: false).") {}; /** + * lombok configuration: {@code lombok.anyConstructor.addConstructorProperties} = {@code true} | {@code false}. + * + * If {@code true}, all generated constructors with at least 1 argument get a {@code @ConstructorProperties}. + * + */ + public static final ConfigurationKey<Boolean> ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES = new ConfigurationKey<Boolean>("lombok.anyConstructor.addConstructorProperties", "Generate @ConstructorProperties for generated constructors (default: false).") {}; + + /** * lombok configuration: {@code lombok.allArgsConstructor.flagUsage} = {@code WARNING} | {@code ERROR}. * * If set, <em>any</em> usage of {@code @AllArgsConstructor} results in a warning / error. diff --git a/src/core/lombok/ToString.java b/src/core/lombok/ToString.java index 18c3d9e3..0c43c40b 100644 --- a/src/core/lombok/ToString.java +++ b/src/core/lombok/ToString.java @@ -64,7 +64,7 @@ public @interface ToString { * Include the result of the superclass's implementation of {@code toString} in the output. * <strong>default: false</strong> * - * @return Whether to call the superclass's {@code equals} implementation as part of the generated equals algorithm. + * @return Whether to call the superclass's {@code toString} implementation as part of the generated toString algorithm. */ boolean callSuper() default false; diff --git a/src/core/lombok/bytecode/AsmUtil.java b/src/core/lombok/bytecode/AsmUtil.java index 26e5af1f..e3d33efa 100644 --- a/src/core/lombok/bytecode/AsmUtil.java +++ b/src/core/lombok/bytecode/AsmUtil.java @@ -37,7 +37,7 @@ class AsmUtil { ClassReader reader = new ClassReader(byteCode); ClassWriter writer = new FixedClassWriter(reader, 0); - ClassVisitor visitor = new ClassVisitor(Opcodes.ASM5, writer) { + ClassVisitor visitor = new ClassVisitor(Opcodes.ASM6, writer) { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new JSRInlinerAdapter(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc, signature, exceptions); } diff --git a/src/core/lombok/bytecode/PreventNullAnalysisRemover.java b/src/core/lombok/bytecode/PreventNullAnalysisRemover.java index 5f2f5f18..c06f2d7c 100644 --- a/src/core/lombok/bytecode/PreventNullAnalysisRemover.java +++ b/src/core/lombok/bytecode/PreventNullAnalysisRemover.java @@ -50,7 +50,7 @@ public class PreventNullAnalysisRemover implements PostCompilerTransformation { class PreventNullAnalysisVisitor extends MethodVisitor { PreventNullAnalysisVisitor(MethodVisitor mv) { - super(Opcodes.ASM5, mv); + super(Opcodes.ASM6, mv); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { @@ -68,7 +68,7 @@ public class PreventNullAnalysisRemover implements PostCompilerTransformation { } } - reader.accept(new ClassVisitor(Opcodes.ASM5, writer) { + reader.accept(new ClassVisitor(Opcodes.ASM6, writer) { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new PreventNullAnalysisVisitor(super.visitMethod(access, name, desc, signature, exceptions)); } diff --git a/src/core/lombok/bytecode/SneakyThrowsRemover.java b/src/core/lombok/bytecode/SneakyThrowsRemover.java index 8ef64e59..a2ee59ea 100644 --- a/src/core/lombok/bytecode/SneakyThrowsRemover.java +++ b/src/core/lombok/bytecode/SneakyThrowsRemover.java @@ -47,12 +47,12 @@ public class SneakyThrowsRemover implements PostCompilerTransformation { ClassReader reader = new ClassReader(fixedByteCode); ClassWriter writer = new ClassWriter(reader, 0); - + final AtomicBoolean changesMade = new AtomicBoolean(); class SneakyThrowsRemoverVisitor extends MethodVisitor { SneakyThrowsRemoverVisitor(MethodVisitor mv) { - super(Opcodes.ASM5, mv); + super(Opcodes.ASM6, mv); } private boolean methodInsnQueued = false; diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java index 2810eec3..98f1e575 100644 --- a/src/core/lombok/core/Version.java +++ b/src/core/lombok/core/Version.java @@ -30,9 +30,9 @@ 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.16.18"; -// private static final String RELEASE_NAME = "Edgy Guinea Pig"; - private static final String RELEASE_NAME = "Dancing Elephant"; + private static final String VERSION = "1.16.21"; + private static final String RELEASE_NAME = "Edgy Guinea Pig"; +// private static final String RELEASE_NAME = "Dancing Elephant"; // Named version history: // Angry Butterfly diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 6c3a0b79..f4705e5b 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -113,7 +113,7 @@ public class HandlerUtil { public static boolean shouldAddGenerated(LombokNode<?, ?, ?> node) { Boolean add = node.getAst().readConfiguration(ConfigurationKeys.ADD_JAVAX_GENERATED_ANNOTATIONS); if (add != null) return add; - return !Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_GENERATED_ANNOTATIONS)); + return Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_GENERATED_ANNOTATIONS)); } public static void handleExperimentalFlagUsage(LombokNode<?, ?, ?> node, ConfigurationKey<FlagUsageType> key, String featureName) { diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 5f2e8fe3..12b8f6bc 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -218,7 +218,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name); bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX); - MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, ast); + MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast); if (md != null) injectMethod(tdParent, md); } addObtainVia(bfd, fieldNode); @@ -580,6 +580,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { inv.sourceEnd = source.sourceEnd; inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L); inv.selector = bfd.nameOfDefaultProvider; + inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); args.add(new ConditionalExpression( new SingleNameReference(bfd.nameOfSetFlag, 0L), @@ -614,14 +615,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0); else invoke.receiver = new QualifiedThisReference(new SingleTypeReference(type.up().getName().toCharArray(), 0) , 0, 0); - TypeParameter[] tps = ((TypeDeclaration) type.get()).typeParameters; - if (tps != null) { - TypeReference[] trs = new TypeReference[tps.length]; - for (int i = 0; i < trs.length; i++) { - trs[i] = new SingleTypeReference(tps[i].name, 0); - } - invoke.typeArguments = trs; - } + + invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]); if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) { statements.add(invoke); @@ -634,10 +629,21 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { return out; } - public MethodDeclaration generateDefaultProvider(char[] methodName, EclipseNode fieldNode, ASTNode source) { + private TypeReference[] typeParameterNames(TypeParameter[] typeParameters) { + if (typeParameters == null) return null; + + TypeReference[] trs = new TypeReference[typeParameters.length]; + for (int i = 0; i < trs.length; i++) { + trs[i] = new SingleTypeReference(typeParameters[i].name, 0); + } + return trs; + } + + public MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult); + out.typeParameters = copyTypeParams(typeParameters, source); out.selector = methodName; out.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic; out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 856f3611..4263e3e9 100644 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -293,7 +293,7 @@ public class HandleConstructor { return new Annotation[] { ann }; } - public static ConstructorDeclaration createConstructor( + @SuppressWarnings("deprecation") public static ConstructorDeclaration createConstructor( AccessLevel level, EclipseNode type, Collection<EclipseNode> fields, boolean allToDefault, EclipseNode sourceNode, List<Annotation> onConstructor) { @@ -305,11 +305,13 @@ public class HandleConstructor { if (isEnum) level = AccessLevel.PRIVATE; - boolean suppressConstructorProperties; + boolean addConstructorProperties; if (fields.isEmpty()) { - suppressConstructorProperties = false; + addConstructorProperties = false; } else { - suppressConstructorProperties = Boolean.TRUE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); + Boolean v = type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES); + addConstructorProperties = v != null ? v.booleanValue() : + Boolean.FALSE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); } ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); @@ -350,7 +352,7 @@ public class HandleConstructor { Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN); Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN); if (nonNulls.length != 0) { - Statement nullCheck = generateNullCheck(field, sourceNode); + Statement nullCheck = generateNullCheck(parameter, sourceNode); if (nullCheck != null) nullChecks.add(nullCheck); } parameter.annotations = copyAnnotations(source, nonNulls, nullables); @@ -364,7 +366,7 @@ public class HandleConstructor { /* Generate annotations that must be put on the generated method, and attach them. */ { Annotation[] constructorProperties = null; - if (!allToDefault && !suppressConstructorProperties && !isLocalType(type)) { + if (!allToDefault && addConstructorProperties && !isLocalType(type)) { constructorProperties = createConstructorProperties(source, fields); } diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 37fa78ab..0d0f51db 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -299,7 +299,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH /* final int PRIME = X; */ { /* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */ - if (!isEmpty || callSuper) { + if (!isEmpty) { LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE); setGeneratedBy(primeDecl, source); primeDecl.modifiers |= Modifier.FINAL; @@ -311,26 +311,30 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH } } - /* int result = 1; */ { - LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE); + /*int result = ... */{ + LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE); setGeneratedBy(resultDecl, source); - resultDecl.initialization = makeIntLiteral("1".toCharArray(), source); + final Expression init; + if (callSuper) { + /* ... super.hashCode(); */ + MessageSend callToSuper = new MessageSend(); + setGeneratedBy(callToSuper, source); + callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; + callToSuper.receiver = new SuperReference(pS, pE); + setGeneratedBy(callToSuper.receiver, source); + callToSuper.selector = "hashCode".toCharArray(); + init = callToSuper; + } else { + /* ... 1; */ + init = makeIntLiteral("1".toCharArray(), source); + } + resultDecl.initialization = init; resultDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0); resultDecl.type.sourceStart = pS; resultDecl.type.sourceEnd = pE; setGeneratedBy(resultDecl.type, source); statements.add(resultDecl); } - if (callSuper) { - MessageSend callToSuper = new MessageSend(); - setGeneratedBy(callToSuper, source); - callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; - callToSuper.receiver = new SuperReference(pS, pE); - setGeneratedBy(callToSuper.receiver, source); - callToSuper.selector = "hashCode".toCharArray(); - statements.add(createResultCalculation(source, callToSuper)); - } - for (EclipseNode field : fields) { TypeReference fType = getFieldType(field, fieldAccess); char[] dollarFieldName = ("$" + field.getName()).toCharArray(); diff --git a/src/core/lombok/javac/CapturingDiagnosticListener.java b/src/core/lombok/javac/CapturingDiagnosticListener.java index a0ac6adc..0e64ed8d 100644 --- a/src/core/lombok/javac/CapturingDiagnosticListener.java +++ b/src/core/lombok/javac/CapturingDiagnosticListener.java @@ -52,6 +52,10 @@ public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileO "^" + Pattern.quote(file.getAbsolutePath()) + "\\s*:\\s*\\d+\\s*:\\s*(?:warning:\\s*)?(.*)$", Pattern.DOTALL).matcher(msg); if (m.matches()) msg = m.group(1); + if (msg.equals("deprecated item is not annotated with @Deprecated")) { + // This is new in JDK9; prior to that you don't see this. We shall ignore these. + return; + } messages.add(new CompilerMessage(d.getLineNumber(), d.getStartPosition(), d.getKind() == Kind.ERROR, msg)); } diff --git a/src/core/lombok/javac/Javac8BasedLombokOptions.java b/src/core/lombok/javac/Javac8BasedLombokOptions.java index 3fdea890..9a662490 100644 --- a/src/core/lombok/javac/Javac8BasedLombokOptions.java +++ b/src/core/lombok/javac/Javac8BasedLombokOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * Copyright (C) 2013-2017 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 @@ -28,7 +28,7 @@ import com.sun.tools.javac.util.Options; public class Javac8BasedLombokOptions extends LombokOptions { public static Javac8BasedLombokOptions replaceWithDelombokOptions(Context context) { Options options = Options.instance(context); - context.put(optionsKey, (Options)null); + context.put(optionsKey, (Options) null); Javac8BasedLombokOptions result = new Javac8BasedLombokOptions(context); result.putAll(options); return result; diff --git a/src/core/lombok/javac/Javac9BasedLombokOptions.java b/src/core/lombok/javac/Javac9BasedLombokOptions.java new file mode 100644 index 00000000..e786346d --- /dev/null +++ b/src/core/lombok/javac/Javac9BasedLombokOptions.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 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.javac; + +import com.sun.tools.javac.main.Option; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Options; + +public class Javac9BasedLombokOptions extends LombokOptions { + public static Javac9BasedLombokOptions replaceWithDelombokOptions(Context context) { + Options options = Options.instance(context); + context.put(optionsKey, (Options) null); + Javac9BasedLombokOptions result = new Javac9BasedLombokOptions(context); + result.putAll(options); + return result; + } + + private Javac9BasedLombokOptions(Context context) { + super(context); + } + + @Override public void putJavacOption(String optionName, String value) { + if (optionName.equals("CLASSPATH")) optionName = "CLASS_PATH"; + if (optionName.equals("SOURCEPATH")) optionName = "SOURCE_PATH"; + if (optionName.equals("BOOTCLASSPATH")) optionName = "BOOT_CLASS_PATH"; + String optionText = Option.valueOf(optionName).primaryName; + put(optionText, value); + } +} diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 91ed325f..af812498 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -48,8 +48,6 @@ import com.sun.tools.javac.tree.JCTree.JCCatch; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCExpression; -import com.sun.tools.javac.tree.JCTree.JCFieldAccess; -import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTry; @@ -106,27 +104,6 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { return cu.sourcefile == null ? null : cu.sourcefile.toString(); } - // jdk9 support, types have changed, names stay the same - static class PackageName { - private static final Method packageNameMethod; - - static { - Method m = null; - try { - m = JCCompilationUnit.class.getDeclaredMethod("getPackageName"); - } catch (Exception e) {} - packageNameMethod = m; - } - - static String getPackageName(JCCompilationUnit cu) { - try { - Object pkg = packageNameMethod.invoke(cu); - return (pkg instanceof JCFieldAccess || pkg instanceof JCIdent) ? pkg.toString() : null; - } catch (Exception e) {} - return null; - } - } - public Context getContext() { return context; } @@ -584,7 +561,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { @Override void error1(DiagnosticPosition pos, String message) { try { - logMethod.invoke(multiple, pos, "proc.messager", message); + logMethod.invoke(log, multiple, pos, "proc.messager", new Object[] { message }); } catch (Throwable t) {} } } diff --git a/src/core/lombok/javac/JavacImportList.java b/src/core/lombok/javac/JavacImportList.java index 0f789f45..468d8c7b 100644 --- a/src/core/lombok/javac/JavacImportList.java +++ b/src/core/lombok/javac/JavacImportList.java @@ -26,7 +26,6 @@ import java.util.Collection; import lombok.core.ImportList; import lombok.core.LombokInternalAliasing; -import lombok.javac.JavacAST.PackageName; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 67dbaac6..8cc239e1 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2015 The Project Lombok Authors. + * Copyright (C) 2011-2018 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 @@ -31,6 +31,7 @@ import java.util.ArrayDeque; import java.util.Map; import javax.lang.model.type.TypeKind; +import javax.tools.JavaFileObject; import lombok.Lombok; import lombok.core.debug.AssertionLogger; @@ -59,6 +60,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; public class JavacResolution { private final Attr attr; @@ -142,9 +144,14 @@ public class JavacResolution { TreeMirrorMaker mirrorMaker = new TreeMirrorMaker(node.getTreeMaker(), node.getContext()); JCTree copy = mirrorMaker.copy(finder.copyAt()); - - memberEnterAndAttribute(copy, finder.get(), node.getContext()); - return mirrorMaker.getOriginalToCopyMap(); + Log log = Log.instance(node.getContext()); + JavaFileObject oldFileObject = log.useSource(((JCCompilationUnit) node.top().get()).getSourceFile()); + try { + memberEnterAndAttribute(copy, finder.get(), node.getContext()); + return mirrorMaker.getOriginalToCopyMap(); + } finally { + log.useSource(oldFileObject); + } } finally { messageSuppressor.enableLoggers(); } @@ -222,8 +229,13 @@ public class JavacResolution { } private void attrib(JCTree tree, Env<AttrContext> env) { + if (env.enclClass.type == null) try { + env.enclClass.type = Type.noType; + } catch (Throwable ignore) { + // This addresses issue #1553 which involves JDK9; if it doesn't exist, we probably don't need to set it. + } if (tree instanceof JCBlock) attr.attribStat(tree, env); - else if (tree instanceof JCMethodDecl) attr.attribStat(((JCMethodDecl)tree).body, env); + else if (tree instanceof JCMethodDecl) attr.attribStat(((JCMethodDecl) tree).body, env); else if (tree instanceof JCVariableDecl) attr.attribStat(tree, env); else throw new IllegalStateException("Called with something that isn't a block, method decl, or variable decl"); } @@ -261,6 +273,7 @@ public class JavacResolution { } public static Type ifTypeIsIterableToComponent(Type type, JavacAST ast) { + if (type == null) return null; Types types = Types.instance(ast.getContext()); Symtab syms = Symtab.instance(ast.getContext()); Type boundType = ReflectiveAccess.Types_upperBound(types, type); diff --git a/src/core/lombok/javac/apt/LombokFileObjects.java b/src/core/lombok/javac/apt/LombokFileObjects.java index 4edf7f6e..7184629f 100644 --- a/src/core/lombok/javac/apt/LombokFileObjects.java +++ b/src/core/lombok/javac/apt/LombokFileObjects.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2017 The Project Lombok Authors. + * Copyright (C) 2010-2018 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 @@ -22,12 +22,18 @@ package lombok.javac.apt; +import java.io.IOException; import java.lang.reflect.Method; import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import javax.tools.FileObject; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; @@ -95,30 +101,42 @@ final class LombokFileObjects { private LombokFileObjects() {} + private static final List<String> KNOWN_JAVA9_FILE_MANAGERS = Arrays.asList( + "com.google.errorprone.MaskedClassLoader$MaskedFileManager", + "com.google.devtools.build.buildjar.javac.BlazeJavacMain$ClassloaderMaskingFileManager", + "com.google.devtools.build.java.turbine.javac.JavacTurbineCompiler$ClassloaderMaskingFileManager", + "org.netbeans.modules.java.source.parsing.ProxyFileManager", + "com.sun.tools.javac.api.ClientCodeWrapper$WrappedStandardJavaFileManager" + ); + static Compiler getCompiler(JavaFileManager jfm) { String jfmClassName = jfm != null ? jfm.getClass().getName() : "null"; if (jfmClassName.equals("com.sun.tools.javac.util.DefaultFileManager")) return Compiler.JAVAC6; if (jfmClassName.equals("com.sun.tools.javac.util.JavacFileManager")) return Compiler.JAVAC6; - if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager") || - jfmClassName.equals("com.google.errorprone.MaskedClassLoader$MaskedFileManager") || - jfmClassName.equals("com.google.devtools.build.buildjar.javac.BlazeJavacMain$ClassloaderMaskingFileManager")) { + if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager")) { try { Class<?> superType = Class.forName("com.sun.tools.javac.file.BaseFileManager"); if (superType.isInstance(jfm)) { return new Java9Compiler(jfm); } } - catch (Exception e) {} + catch (Throwable e) {} return Compiler.JAVAC7; } + if (KNOWN_JAVA9_FILE_MANAGERS.contains(jfmClassName)) { + try { + return new Java9Compiler(jfm); + } + catch (Throwable e) {} + } try { if (Class.forName("com.sun.tools.javac.file.BaseFileObject") == null) throw new NullPointerException(); return Compiler.JAVAC7; - } catch (Exception e) {} + } catch (Throwable e) {} try { if (Class.forName("com.sun.tools.javac.util.BaseFileObject") == null) throw new NullPointerException(); return Compiler.JAVAC6; - } catch (Exception e) {} + } catch (Throwable e) {} StringBuilder sb = new StringBuilder(jfmClassName); if (jfm != null) { @@ -142,25 +160,108 @@ final class LombokFileObjects { private final BaseFileManager fileManager; public Java9Compiler(JavaFileManager jfm) { - fileManager = (BaseFileManager) jfm; + fileManager = asBaseFileManager(jfm); } @Override public JavaFileObject wrap(LombokFileObject fileObject) { + return new Javac9BaseFileObjectWrapper(fileManager, toPath(fileObject), fileObject); + } + + @Override public Method getDecoderMethod() { + return null; + } + + private static Path toPath(LombokFileObject fileObject) { URI uri = fileObject.toUri(); if (uri.getScheme() == null) { uri = URI.create("file:///" + uri); } - Path path; try { - path = Paths.get(uri); + return Paths.get(uri); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Problems in URI '" + uri + "' (" + fileObject.toUri() + ")", e); } - return new Javac9BaseFileObjectWrapper(fileManager, path, fileObject); } - @Override public Method getDecoderMethod() { - throw new UnsupportedOperationException(); + private static BaseFileManager asBaseFileManager(JavaFileManager jfm) { + if (jfm instanceof BaseFileManager) { + return (BaseFileManager) jfm; + } + return new FileManagerWrapper(jfm); + } + + static class FileManagerWrapper extends BaseFileManager { + JavaFileManager manager; + + public FileManagerWrapper(JavaFileManager manager) { + super(null); + this.manager = manager; + } + + @Override + public int isSupportedOption(String option) { + return manager.isSupportedOption(option); + } + + @Override + public ClassLoader getClassLoader(Location location) { + return manager.getClassLoader(location); + } + + @Override + public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException { + return manager.list(location, packageName, kinds, recurse); + } + + @Override + public String inferBinaryName(Location location, JavaFileObject file) { + return manager.inferBinaryName(location, file); + } + + @Override + public boolean isSameFile(FileObject a, FileObject b) { + return manager.isSameFile(a, b); + } + + @Override + public boolean handleOption(String current, Iterator<String> remaining) { + return manager.handleOption(current, remaining); + } + + @Override + public boolean hasLocation(Location location) { + return manager.hasLocation(location); + } + + @Override + public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException { + return manager.getJavaFileForInput(location, className, kind); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { + return manager.getJavaFileForOutput(location, className, kind, sibling); + } + + @Override + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { + return manager.getFileForInput(location, packageName, relativeName); + } + + @Override + public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException { + return manager.getFileForOutput(location, packageName, relativeName, sibling); + } + + @Override + public void flush() throws IOException { + manager.flush(); + } + + @Override + public void close() throws IOException { + manager.close(); + } } } } diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java index b962a955..5c7e47ee 100644 --- a/src/core/lombok/javac/apt/LombokProcessor.java +++ b/src/core/lombok/javac/apt/LombokProcessor.java @@ -54,6 +54,8 @@ import lombok.javac.JavacTransformer; import com.sun.source.util.TreePath; import com.sun.source.util.Trees; +import com.sun.tools.javac.jvm.ClassWriter; +import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.processing.JavacFiler; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; @@ -156,7 +158,6 @@ public class LombokProcessor extends AbstractProcessor { @SuppressWarnings("unchecked") Map<Object,Object> ht = (Map<Object,Object>) htField.get(context); final JavaFileManager originalFiler = (JavaFileManager) ht.get(key); - if (!(originalFiler instanceof InterceptingJavaFileManager)) { final Messager messager = processingEnv.getMessager(); DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager); @@ -166,11 +167,37 @@ public class LombokProcessor extends AbstractProcessor { Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager"); filerFileManagerField.setAccessible(true); filerFileManagerField.set(processingEnv.getFiler(), newFiler); + + replaceFileManagerJdk9(context, newFiler); } } catch (Exception e) { throw Lombok.sneakyThrow(e); } } + + private void replaceFileManagerJdk9(Context context, JavaFileManager newFiler) { + try { + JavaCompiler compiler = (JavaCompiler) JavaCompiler.class.getDeclaredMethod("instance", Context.class).invoke(null, context); + try { + Field fileManagerField = JavaCompiler.class.getDeclaredField("fileManager"); + fileManagerField.setAccessible(true); + fileManagerField.set(compiler, newFiler); + } + catch (Exception e) {} + + try { + Field writerField = JavaCompiler.class.getDeclaredField("writer"); + writerField.setAccessible(true); + ClassWriter writer = (ClassWriter) writerField.get(compiler); + Field fileManagerField = ClassWriter.class.getDeclaredField("fileManager"); + fileManagerField.setAccessible(true); + fileManagerField.set(writer, newFiler); + } + catch (Exception e) {} + } + catch (Exception e) { + } + } private void forceMultipleRoundsInNetBeansEditor() { try { diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 157828a0..d5a342e4 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 The Project Lombok Authors. + * Copyright (C) 2013-2018 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 @@ -171,7 +171,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (isDefault != null) { bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name); bfd.nameOfSetFlag = parent.toName(bfd.name + "$set"); - JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode); + JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); if (md != null) injectMethod(tdParent, md); } @@ -212,7 +212,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { thrownExceptions = jmd.thrown; nameOfBuilderMethod = jmd.name; if (returnType instanceof JCTypeApply) { - returnType = ((JCTypeApply) returnType).clazz; + returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext()); } if (builderClassName.isEmpty()) { if (returnType instanceof JCFieldAccess) { @@ -232,7 +232,16 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (Character.isLowerCase(builderClassName.charAt(0))) { builderClassName = Character.toTitleCase(builderClassName.charAt(0)) + builderClassName.substring(1); } - } else { + } else if (returnType instanceof JCTypeApply) { + JCExpression clazz = ((JCTypeApply) returnType).clazz; + if (clazz instanceof JCFieldAccess) { + builderClassName = ((JCFieldAccess) clazz).name + "Builder"; + } else if (clazz instanceof JCIdent) { + builderClassName = ((JCIdent) clazz).name + "Builder"; + } + } + + if (builderClassName.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"; @@ -253,11 +262,14 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { tpOnRet = ((JCTypeApply) fullReturnType).arguments; } - if (returnType instanceof JCIdent) { - simpleName = ((JCIdent) returnType).name; + JCExpression namingType = returnType; + if (returnType instanceof JCTypeApply) namingType = ((JCTypeApply) returnType).clazz; + + if (namingType instanceof JCIdent) { + simpleName = ((JCIdent) namingType).name; pkg = null; - } else if (returnType instanceof JCFieldAccess) { - JCFieldAccess jcfa = (JCFieldAccess) returnType; + } else if (namingType instanceof JCFieldAccess) { + JCFieldAccess jcfa = (JCFieldAccess) namingType; simpleName = jcfa.name; pkg = unpack(jcfa.selected); if (pkg.startsWith("ERR:")) { @@ -266,7 +278,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return; } } else { - annotationNode.addError("Expected a (parameterized) type here instead of a " + returnType.getClass().getName()); + annotationNode.addError("Expected a (parameterized) type here instead of a " + namingType.getClass().getName()); return; } @@ -542,11 +554,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); for (BuilderFieldData bfd : builderFields) { if (bfd.nameOfSetFlag != null) { - args.append(maker.Conditional(maker.Ident(bfd.nameOfSetFlag), maker.Ident(bfd.name), - maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))); - } else { - args.append(maker.Ident(bfd.name)); + statements.append(maker.VarDef(maker.Modifiers(0L), bfd.name, cloneType(maker, bfd.type, source, tdParent.getContext()), maker.Select(maker.Ident(type.toName("this")), bfd.name))); + statements.append(maker.If(maker.Unary(CTC_NOT, maker.Ident(bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.name),maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null)); } + args.append(maker.Ident(bfd.name)); } if (addCleaning) { @@ -577,7 +588,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null); } - public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode) { + public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List<JCTypeParameter> params) { JavacTreeMaker maker = fieldNode.getTreeMaker(); JCVariableDecl field = (JCVariableDecl) fieldNode.get(); @@ -586,7 +597,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); int modifiers = Flags.PRIVATE | Flags.STATIC; - return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); + return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) { diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index 56036963..b3261379 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -260,18 +260,20 @@ public class HandleConstructor { mods.annotations = mods.annotations.append(annotation); } - public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean allToDefault, JavacNode source) { + @SuppressWarnings("deprecation") public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean allToDefault, JavacNode source) { JavacTreeMaker maker = typeNode.getTreeMaker(); boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0; if (isEnum) level = AccessLevel.PRIVATE; - boolean suppressConstructorProperties; + boolean addConstructorProperties; if (fields.isEmpty()) { - suppressConstructorProperties = false; + addConstructorProperties = false; } else { - suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); + Boolean v = typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES); + addConstructorProperties = v != null ? v.booleanValue() : + Boolean.FALSE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); } ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>(); @@ -289,7 +291,7 @@ public class HandleConstructor { JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, field.vartype, null); params.append(param); if (!nonNulls.isEmpty()) { - JCStatement nullCheck = generateNullCheck(maker, fieldNode, source); + JCStatement nullCheck = generateNullCheck(maker, fieldNode, param, source); if (nullCheck != null) nullChecks.append(nullCheck); } } @@ -299,7 +301,7 @@ public class HandleConstructor { } JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil()); - if (!allToDefault && !suppressConstructorProperties && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) { + if (!allToDefault && addConstructorProperties && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) { addConstructorProperties(mods, typeNode, fields); } if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor)); diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 4bd1ce4b..da2db909 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -258,20 +258,23 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext()); /* final int PRIME = X; */ { - if (!fields.isEmpty() || callSuper) { + if (!fields.isEmpty()) { statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(HandlerUtil.primeForHashcode()))); } } - /* int result = 1; */ { - statements.append(maker.VarDef(maker.Modifiers(0), resultName, maker.TypeIdent(CTC_INT), maker.Literal(1))); - } - - if (callSuper) { - JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(), - maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")), - List.<JCExpression>nil()); - statements.append(createResultCalculation(typeNode, callToSuper)); + /* int result = ... */ { + final JCExpression init; + if (callSuper) { + /* ... super.hashCode(); */ + init = maker.Apply(List.<JCExpression>nil(), + maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")), + List.<JCExpression>nil()); + } else { + /* ... 1; */ + init = maker.Literal(1); + } + statements.append(maker.VarDef(maker.Modifiers(0), resultName, maker.TypeIdent(CTC_INT), init)); } Name dollar = typeNode.toName("$"); diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 2976eabe..f0f6eb2a 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2016 The Project Lombok Authors. + * Copyright (C) 2010-2018 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 @@ -62,21 +62,21 @@ public class HandleVal extends JavacASTAdapter { JCTree typeTree = local.vartype; if (typeTree == null) return; String typeTreeToString = typeTree.toString(); - + if (!(eq(typeTreeToString, "val") || eq(typeTreeToString, "var"))) return; boolean isVal = typeMatches(val.class, localNode, typeTree); boolean isVar = typeMatches(var.class, localNode, typeTree); if (!(isVal || isVar)) return; - + if (isVal) handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val"); if (isVar) handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var"); - + JCTree parentRaw = localNode.directUp().get(); if (isVal && parentRaw instanceof JCForLoop) { localNode.addError("'val' is not allowed in old-style for loops"); return; } - + JCExpression rhsOfEnhancedForLoop = null; if (local.init == null) { if (parentRaw instanceof JCEnhancedForLoop) { @@ -84,26 +84,25 @@ public class HandleVal extends JavacASTAdapter { if (efl.var == local) rhsOfEnhancedForLoop = efl.expr; } } - + final String annotation = typeTreeToString; if (rhsOfEnhancedForLoop == null && local.init == null) { localNode.addError("'" + annotation + "' on a local variable requires an initializer expression"); return; - } - + if (local.init instanceof JCNewArray && ((JCNewArray)local.init).elemtype == null) { localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })"); return; } - + if (localNode.shouldDeleteLombokAnnotations()) { JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, val.class.getName()); JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, var.class.getName()); } - + if (isVal) local.mods.flags |= Flags.FINAL; - + if (!localNode.shouldDeleteLombokAnnotations()) { JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeTree, localNode.getContext()); local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation); @@ -126,7 +125,7 @@ public class HandleVal extends JavacASTAdapter { try { type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type; } catch (RuntimeException e) { - System.err.println("Exception while resolving: " + localNode); + System.err.println("Exception while resolving: " + localNode + "(" + localNode.getFileName() + ")"); throw e; } } else { @@ -137,7 +136,7 @@ public class HandleVal extends JavacASTAdapter { local.type = Symtab.instance(localNode.getContext()).unknownType; type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type; } catch (RuntimeException e) { - System.err.println("Exception while resolving: " + localNode); + System.err.println("Exception while resolving: " + localNode + "(" + localNode.getFileName() + ")"); throw e; } } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 1ec2939e..956ab446 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1211,16 +1211,25 @@ public class JavacHandlerUtil { } /** - * Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the + * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the * variable name as message. - * - * @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}. */ public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JavacNode source) { + return generateNullCheck(maker, variable, (JCVariableDecl)variable.get(), source); + } + + /** + * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the + * variable name as message. + * + * This is a special case method reserved for use when the provided declaration differs from the + * variable's declaration, i.e. in a constructor or setter where the local parameter is named the same but with the prefix + * stripped as a result of @Accessors.prefix. + */ + public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JCVariableDecl varDecl, JavacNode source) { NullCheckExceptionType exceptionType = source.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE); if (exceptionType == null) exceptionType = NullCheckExceptionType.NULL_POINTER_EXCEPTION; - JCVariableDecl varDecl = (JCVariableDecl) variable.get(); if (isPrimitive(varDecl.vartype)) return null; Name fieldName = varDecl.name; JCExpression exType = genTypeRef(variable, exceptionType.getExceptionType()); @@ -1379,17 +1388,18 @@ public class JavacHandlerUtil { } public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, Name typeName, List<JCTypeParameter> params) { + if (params.isEmpty()) { + return maker.Ident(typeName); + } + return maker.TypeApply(maker.Ident(typeName), typeParameterNames(maker, params)); + } + + public static List<JCExpression> typeParameterNames(JavacTreeMaker maker, List<JCTypeParameter> params) { ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - - if (!params.isEmpty()) { - for (JCTypeParameter param : params) { - typeArgs.append(maker.Ident(param.name)); - } - - return maker.TypeApply(maker.Ident(typeName), typeArgs.toList()); + for (JCTypeParameter param : params) { + typeArgs.append(maker.Ident(param.name)); } - - return maker.Ident(typeName); + return typeArgs.toList(); } public static void sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(JavacNode typeNode, JavacNode errorNode) { |