diff options
Diffstat (limited to 'src/core/lombok/javac')
46 files changed, 783 insertions, 399 deletions
diff --git a/src/core/lombok/javac/CompilerMessageSuppressor.java b/src/core/lombok/javac/CompilerMessageSuppressor.java index 02dc6c26..7d7b81e6 100644 --- a/src/core/lombok/javac/CompilerMessageSuppressor.java +++ b/src/core/lombok/javac/CompilerMessageSuppressor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 The Project Lombok Authors. + * Copyright (C) 2011-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -226,7 +226,7 @@ public final class CompilerMessageSuppressor { ListBuffer<Object> newDeferredDiagnostics = new ListBuffer<Object>(); for (Object diag_ : deferredDiagnostics) { if (!(diag_ instanceof JCDiagnostic)) { - newDeferredDiagnostics.add(diag_); + newDeferredDiagnostics.append(diag_); continue; } JCDiagnostic diag = (JCDiagnostic) diag_; @@ -234,7 +234,7 @@ public final class CompilerMessageSuppressor { if (here >= startPos && here < endPos && diag.getSource() == sourcefile) { // We eliminate it } else { - newDeferredDiagnostics.add(diag); + newDeferredDiagnostics.append(diag); } } field.set(receiver, newDeferredDiagnostics); diff --git a/src/core/lombok/javac/JavacAugments.java b/src/core/lombok/javac/JavacAugments.java index bc23131b..e5d1fc43 100644 --- a/src/core/lombok/javac/JavacAugments.java +++ b/src/core/lombok/javac/JavacAugments.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,7 @@ package lombok.javac; import lombok.core.FieldAugment; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCImport; public final class JavacAugments { private JavacAugments() { @@ -32,4 +33,5 @@ public final class JavacAugments { public static final FieldAugment<JCTree, Boolean> JCTree_handled = FieldAugment.augment(JCTree.class, boolean.class, "lombok$handled"); public static final FieldAugment<JCTree, JCTree> JCTree_generatedNode = FieldAugment.circularSafeAugment(JCTree.class, JCTree.class, "lombok$generatedNode"); + public static final FieldAugment<JCImport, Boolean> JCImport_deletable = FieldAugment.circularSafeAugment(JCImport.class, Boolean.class, "lombok$deletable"); } diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 3de3f38b..035f7c53 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2020 The Project Lombok Authors. + * Copyright (C) 2009-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -186,16 +186,6 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre return false; } - @Override protected boolean fieldContainsAnnotation(JCTree field, JCTree annotation) { - if (!(field instanceof JCVariableDecl)) return false; - JCVariableDecl f = (JCVariableDecl) field; - if (f.mods.annotations == null) return false; - for (JCAnnotation childAnnotation : f.mods.annotations) { - if (childAnnotation == annotation) return true; - } - return false; - } - /** * Convenient shortcut to the owning JavacAST object's getTreeMaker method. * diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 63ca69dd..e96079e0 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -71,6 +71,16 @@ public class JavacResolution { private final Attr attr; private final CompilerMessageSuppressor messageSuppressor; + private static final Method isLocal; + + static { + Method local = Permit.permissiveGetMethod(TypeSymbol.class, "isLocal"); + if (local == null) { + local = Permit.permissiveGetMethod(TypeSymbol.class, "isDirectlyOrIndirectlyLocal"); + } + isLocal = local; + } + public JavacResolution(Context context) { attr = Attr.instance(context); messageSuppressor = new CompilerMessageSuppressor(context); @@ -352,6 +362,15 @@ public class JavacResolution { return a.compareTo(b); } + private static boolean isLocalType(TypeSymbol symbol) { + try { + return (Boolean) Permit.invoke(isLocal, symbol); + } + catch (Exception e) { + return false; + } + } + private static JCExpression typeToJCTree0(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid, boolean allowCapture) throws TypeNotConvertibleException { // NB: There's such a thing as maker.Type(type), but this doesn't work very well; it screws up anonymous classes, captures, and adds an extra prefix dot for some reason too. // -- so we write our own take on that here. @@ -450,7 +469,7 @@ public class JavacResolution { } String qName; - if (symbol.isLocal()) { + if (isLocalType(symbol)) { qName = symbol.getSimpleName().toString(); } else if (symbol.type != null && symbol.type.getEnclosingType() != null && typeTag(symbol.type.getEnclosingType()).equals(typeTag("CLASS"))) { replacement = typeToJCTree0(type.getEnclosingType(), ast, false, false, false); diff --git a/src/core/lombok/javac/apt/InterceptingJavaFileObject.java b/src/core/lombok/javac/apt/InterceptingJavaFileObject.java index 403b5672..75cf0713 100644 --- a/src/core/lombok/javac/apt/InterceptingJavaFileObject.java +++ b/src/core/lombok/javac/apt/InterceptingJavaFileObject.java @@ -26,7 +26,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; import java.nio.charset.CharsetDecoder; @@ -35,7 +34,6 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; import javax.tools.JavaFileObject; -import lombok.Lombok; import lombok.core.DiagnosticsReceiver; import lombok.core.PostCompiler; import lombok.permit.Permit; diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java index 6e5e603b..6552f15b 100644 --- a/src/core/lombok/javac/apt/LombokProcessor.java +++ b/src/core/lombok/javac/apt/LombokProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2019 The Project Lombok Authors. + * Copyright (C) 2009-2020 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 @@ -63,6 +63,8 @@ import lombok.core.CleanupRegistry; import lombok.core.DiagnosticsReceiver; import lombok.javac.JavacTransformer; import lombok.permit.Permit; +import lombok.permit.dummy.Parent; +import sun.misc.Unsafe; /** * This Annotation Processor is the standard injection mechanism for lombok-enabling the javac compiler. @@ -430,6 +432,7 @@ public class LombokProcessor extends AbstractProcessor { * gradle incremental compilation, the delegate ProcessingEnvironment of the gradle wrapper is returned. */ public JavacProcessingEnvironment getJavacProcessingEnvironment(Object procEnv) { + addOpensForLombok(); if (procEnv instanceof JavacProcessingEnvironment) return (JavacProcessingEnvironment) procEnv; // try to find a "delegate" field in the object, and use this to try to obtain a JavacProcessingEnvironment @@ -446,7 +449,91 @@ public class LombokProcessor extends AbstractProcessor { "Can't get the delegate of the gradle IncrementalProcessingEnvironment. Lombok won't work."); return null; } - + + private static Object getOwnModule() { + try { + Method m = Permit.getMethod(Class.class, "getModule"); + return m.invoke(LombokProcessor.class); + } catch (Exception e) { + return null; + } + } + + private static Object getJdkCompilerModule() { + /* call public api: ModuleLayer.boot().findModule("jdk.compiler").get(); + but use reflection because we don't want this code to crash on jdk1.7 and below. + In that case, none of this stuff was needed in the first place, so we just exit via + the catch block and do nothing. + */ + + try { + Class<?> cModuleLayer = Class.forName("java.lang.ModuleLayer"); + Method mBoot = cModuleLayer.getDeclaredMethod("boot"); + Object bootLayer = mBoot.invoke(null); + Class<?> cOptional = Class.forName("java.util.Optional"); + Method mFindModule = cModuleLayer.getDeclaredMethod("findModule", String.class); + Object oCompilerO = mFindModule.invoke(bootLayer, "jdk.compiler"); + return cOptional.getDeclaredMethod("get").invoke(oCompilerO); + } catch (Exception e) { + return null; + } + } + + /** Useful from jdk9 and up; required from jdk16 and up. This code is supposed to gracefully do nothing on jdk8 and below, as this operation isn't needed there. */ + public static void addOpensForLombok() { + Class<?> cModule; + try { + cModule = Class.forName("java.lang.Module"); + } catch (ClassNotFoundException e) { + return; //jdk8-; this is not needed. + } + + Unsafe unsafe = getUnsafe(); + Object jdkCompilerModule = getJdkCompilerModule(); + Object ownModule = getOwnModule(); + String[] allPkgs = { + "com.sun.tools.javac.code", + "com.sun.tools.javac.comp", + "com.sun.tools.javac.file", + "com.sun.tools.javac.main", + "com.sun.tools.javac.model", + "com.sun.tools.javac.parser", + "com.sun.tools.javac.processing", + "com.sun.tools.javac.tree", + "com.sun.tools.javac.util", + "com.sun.tools.javac.jvm", + }; + + try { + Method m = cModule.getDeclaredMethod("implAddOpens", String.class, cModule); + long firstFieldOffset = getFirstFieldOffset(unsafe); + unsafe.putBooleanVolatile(m, firstFieldOffset, true); + for (String p : allPkgs) m.invoke(jdkCompilerModule, p, ownModule); + } catch (Exception ignore) {} + } + + private static long getFirstFieldOffset(Unsafe unsafe) { + try { + return unsafe.objectFieldOffset(Parent.class.getDeclaredField("first")); + } catch (NoSuchFieldException e) { + // can't happen. + throw new RuntimeException(e); + } catch (SecurityException e) { + // can't happen + throw new RuntimeException(e); + } + } + + private static Unsafe getUnsafe() { + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + return (Unsafe) theUnsafe.get(null); + } catch (Exception e) { + return null; + } + } + /** * This class returns the given filer as a JavacFiler. In case the filer is no * JavacFiler (e.g. the Gradle IncrementalFiler), its "delegate" field is used to get the JavacFiler diff --git a/src/core/lombok/javac/handlers/HandleAccessors.java b/src/core/lombok/javac/handlers/HandleAccessors.java index 46fe1cd2..60466d78 100644 --- a/src/core/lombok/javac/handlers/HandleAccessors.java +++ b/src/core/lombok/javac/handlers/HandleAccessors.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 The Project Lombok Authors. + * Copyright (C) 2012-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,8 +24,6 @@ package lombok.javac.handlers; import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.handlers.JavacHandlerUtil.*; -import org.mangosdk.spi.ProviderFor; - import com.sun.tools.javac.tree.JCTree.JCAnnotation; import lombok.ConfigurationKeys; @@ -34,8 +32,9 @@ import lombok.core.HandlerPriority; import lombok.experimental.Accessors; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.spi.Provides; -@ProviderFor(JavacAnnotationHandler.class) +@Provides @HandlerPriority(65536) public class HandleAccessors extends JavacAnnotationHandler<Accessors> { @Override public void handle(AnnotationValues<Accessors> annotation, JCAnnotation ast, JavacNode annotationNode) { diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index e867fd63..c23dc14c 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2020 The Project Lombok Authors. + * Copyright (C) 2013-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,8 +30,6 @@ import java.util.ArrayList; import javax.lang.model.element.Modifier; -import org.mangosdk.spi.ProviderFor; - import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; @@ -81,8 +79,9 @@ import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; import lombok.javac.handlers.JavacSingularsRecipes.SingularData; +import lombok.spi.Provides; -@ProviderFor(JavacAnnotationHandler.class) +@Provides @HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes. public class HandleBuilder extends JavacAnnotationHandler<Builder> { private HandleConstructor handleConstructor = new HandleConstructor(); @@ -131,7 +130,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { builderMethodName = ann.builderMethodName(); buildMethodName = ann.buildMethodName(); - builderClassName = fixBuilderClassName(node, ann.builderClassName()); + builderClassName = getBuilderClassNameTemplate(node, ann.builderClassName()); toBuilder = ann.toBuilder(); if (builderMethodName == null) builderMethodName = "builder"; @@ -139,7 +138,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (builderClassName == null) builderClassName = ""; } - static String fixBuilderClassName(JavacNode node, String override) { + static String getBuilderClassNameTemplate(JavacNode node, String override) { if (override != null && !override.isEmpty()) return override; override = node.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME); if (override != null && !override.isEmpty()) return override; @@ -147,8 +146,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } String replaceBuilderClassName(Name name) { - if (builderClassName.indexOf('*') == -1) return builderClassName; - return builderClassName.replace("*", name.toString()); + return replaceBuilderClassName(name.toString(), builderClassName); + } + + String replaceBuilderClassName(String name, String template) { + if (template.indexOf('*') == -1) return template; + return template.replace("*", name); } JCExpression createBuilderParentTypeReference() { @@ -193,6 +196,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } @Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) { + final String BUILDER_NODE_NOT_SUPPORTED_ERR = "@Builder is only supported on classes, records, constructors, and methods."; + handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); BuilderJob job = new BuilderJob(); job.sourceNode = annotationNode; @@ -230,6 +235,11 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { ArrayList<JavacNode> nonFinalNonDefaultedFields = null; if (parent.get() instanceof JCClassDecl) { + if (!isClass(parent) && !isRecord(parent)) { + annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR); + return; + } + job.parentType = parent; JCClassDecl td = (JCClassDecl) parent.get(); @@ -280,7 +290,11 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { allFields.append(fieldNode); } - handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + if (!isRecord(parent)) { + // Records ship with a canonical constructor that acts as @AllArgsConstructor - just use that one. + + handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + } buildMethodReturnType = namePlusTypeParamsToTypeReference(parent.getTreeMaker(), parent, td.typarams); job.typeParams = job.builderTypeParams = td.typarams; @@ -388,7 +402,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } } } else { - annotationNode.addError("@Builder is only supported on types, constructors, and methods."); + annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR); return; } @@ -608,10 +622,6 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { private JCMethodDecl generateToBuilderMethod(BuilderJob job, List<JCTypeParameter> typeParameters, String prefix) { // return new ThingieBuilder<A, B>().setA(this.a).setB(this.b); JavacTreeMaker maker = job.getTreeMaker(); - ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - for (JCTypeParameter typeParam : typeParameters) { - typeArgs.append(maker.Ident(typeParam.name)); - } JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderClassName), !job.isStatic, job.builderTypeParams), List.<JCExpression>nil(), null); JCExpression invoke = call; @@ -804,13 +814,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { public JCMethodDecl generateBuilderMethod(BuilderJob job) { //String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) { //builderClassName, annotationNode, tdParent, typeParams, accessForOuters); - - JavacTreeMaker maker = job.getTreeMaker(); - ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); - for (JCTypeParameter typeParam : job.typeParams) { - typeArgs.append(maker.Ident(typeParam.name)); - } + JavacTreeMaker maker = job.getTreeMaker(); JCExpression call; if (job.isStatic) { @@ -876,7 +881,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { bfd.createdFields.add(field); } } - for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, job.sourceNode); + for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, job.sourceNode); } public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) { diff --git a/src/core/lombok/javac/handlers/HandleBuilderDefault.java b/src/core/lombok/javac/handlers/HandleBuilderDefault.java index 54060233..8438057a 100644 --- a/src/core/lombok/javac/handlers/HandleBuilderDefault.java +++ b/src/core/lombok/javac/handlers/HandleBuilderDefault.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2018 The Project Lombok Authors. + * Copyright (C) 2017-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,8 +23,6 @@ package lombok.javac.handlers; import static lombok.javac.handlers.JavacHandlerUtil.*; -import org.mangosdk.spi.ProviderFor; - import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; @@ -36,8 +34,9 @@ import lombok.core.HandlerPriority; import lombok.experimental.SuperBuilder; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.spi.Provides; -@ProviderFor(JavacAnnotationHandler.class) +@Provides @HandlerPriority(-1025) //HandleBuilder's level, minus one. public class HandleBuilderDefault extends JavacAnnotationHandler<Builder.Default> { @Override public void handle(AnnotationValues<Builder.Default> annotation, JCAnnotation ast, JavacNode annotationNode) { diff --git a/src/core/lombok/javac/handlers/HandleBuilderDefaultRemove.java b/src/core/lombok/javac/handlers/HandleBuilderDefaultRemove.java index fc0738c3..d7bc28cb 100644 --- a/src/core/lombok/javac/handlers/HandleBuilderDefaultRemove.java +++ b/src/core/lombok/javac/handlers/HandleBuilderDefaultRemove.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Project Lombok Authors. + * Copyright (C) 2018-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,8 +23,6 @@ package lombok.javac.handlers; import static lombok.javac.handlers.JavacHandlerUtil.*; -import org.mangosdk.spi.ProviderFor; - import com.sun.tools.javac.tree.JCTree.JCAnnotation; import lombok.Builder; @@ -34,9 +32,10 @@ import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.spi.Provides; -@ProviderFor(JavacAnnotationHandler.class) -@HandlerPriority(65536) +@Provides +@HandlerPriority(32768) @AlreadyHandledAnnotations public class HandleBuilderDefaultRemove extends JavacAnnotationHandler<Builder.Default> { @Override public void handle(AnnotationValues<Default> annotation, JCAnnotation ast, JavacNode annotationNode) { diff --git a/src/core/lombok/javac/handlers/HandleBuilder |
