aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lombok')
-rw-r--r--src/core/lombok/ConfigurationKeys.java2
-rw-r--r--src/core/lombok/EqualsAndHashCode.java23
-rw-r--r--src/core/lombok/bytecode/PoolConstantsApp.java8
-rw-r--r--src/core/lombok/bytecode/PostCompilerApp.java7
-rw-r--r--src/core/lombok/bytecode/PreventNullAnalysisRemover.java6
-rw-r--r--src/core/lombok/bytecode/SneakyThrowsRemover.java6
-rw-r--r--src/core/lombok/core/AnnotationProcessor.java63
-rw-r--r--src/core/lombok/core/Main.java8
-rw-r--r--src/core/lombok/core/PostCompiler.java10
-rw-r--r--src/core/lombok/core/PublicApiCreatorApp.java7
-rw-r--r--src/core/lombok/core/Version.java4
-rw-r--r--src/core/lombok/core/configuration/CheckerFrameworkVersion.java6
-rw-r--r--src/core/lombok/core/configuration/ConfigurationApp.java7
-rw-r--r--src/core/lombok/core/handlers/HandlerUtil.java89
-rw-r--r--src/core/lombok/core/handlers/SneakyThrowsAndCleanupDependencyInfo.java7
-rw-r--r--src/core/lombok/core/runtimeDependencies/CreateLombokRuntimeApp.java7
-rw-r--r--src/core/lombok/eclipse/EcjAugments.java (renamed from src/core/lombok/eclipse/EclipseAugments.java)20
-rw-r--r--src/core/lombok/eclipse/EclipseAST.java36
-rw-r--r--src/core/lombok/eclipse/EclipseNode.java2
-rw-r--r--src/core/lombok/eclipse/HandlerLibrary.java2
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java293
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java21
-rw-r--r--src/core/lombok/eclipse/handlers/HandleAccessors.java6
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleBuilder.java613
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilderDefault.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleCleanup.java6
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleConstructor.java25
-rw-r--r--src/core/lombok/eclipse/handlers/HandleData.java8
-rw-r--r--src/core/lombok/eclipse/handlers/HandleDelegate.java6
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java163
-rw-r--r--src/core/lombok/eclipse/handlers/HandleExtensionMethod.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleFieldDefaults.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleGetter.java13
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleHelper.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleJacksonized.java7
-rw-r--r--src/core/lombok/eclipse/handlers/HandleLog.java45
-rw-r--r--src/core/lombok/eclipse/handlers/HandleNonNull.java10
-rw-r--r--src/core/lombok/eclipse/handlers/HandlePrintAST.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java13
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSneakyThrows.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSuperBuilder.java542
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSynchronized.java7
-rw-r--r--src/core/lombok/eclipse/handlers/HandleToString.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleUtilityClass.java27
-rw-r--r--src/core/lombok/eclipse/handlers/HandleVal.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleValue.java10
-rw-r--r--src/core/lombok/eclipse/handlers/HandleWith.java7
-rw-r--r--src/core/lombok/eclipse/handlers/HandleWithBy.java7
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java7
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java7
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java4
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java7
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java10
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java7
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java10
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java6
-rw-r--r--src/core/lombok/javac/CompilerMessageSuppressor.java6
-rw-r--r--src/core/lombok/javac/HandlerLibrary.java2
-rw-r--r--src/core/lombok/javac/Javac6BasedLombokOptions.java2
-rw-r--r--src/core/lombok/javac/JavacAST.java126
-rw-r--r--src/core/lombok/javac/JavacASTVisitor.java26
-rw-r--r--src/core/lombok/javac/JavacNode.java2
-rw-r--r--src/core/lombok/javac/JavacResolution.java41
-rw-r--r--src/core/lombok/javac/apt/InterceptingJavaFileObject.java15
-rw-r--r--src/core/lombok/javac/apt/LombokProcessor.java178
-rw-r--r--src/core/lombok/javac/apt/Processor.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleAccessors.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java606
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilderDefault.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilderDefaultRemove.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilderRemove.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleCleanup.java13
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java33
-rw-r--r--src/core/lombok/javac/handlers/HandleData.java10
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java14
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java136
-rw-r--r--src/core/lombok/javac/handlers/HandleExtensionMethod.java41
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldDefaults.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldNameConstants.java19
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java37
-rwxr-xr-xsrc/core/lombok/javac/handlers/HandleHelper.java11
-rw-r--r--src/core/lombok/javac/handlers/HandleJacksonized.java18
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java42
-rw-r--r--src/core/lombok/javac/handlers/HandleNonNull.java26
-rw-r--r--src/core/lombok/javac/handlers/HandlePrintAST.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java52
-rw-r--r--src/core/lombok/javac/handlers/HandleSneakyThrows.java20
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java715
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilderRemove.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleSynchronized.java15
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java14
-rw-r--r--src/core/lombok/javac/handlers/HandleUtilityClass.java11
-rw-r--r--src/core/lombok/javac/handlers/HandleVal.java12
-rw-r--r--src/core/lombok/javac/handlers/HandleValue.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleWith.java12
-rw-r--r--src/core/lombok/javac/handlers/HandleWithBy.java17
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java266
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java81
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java7
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java7
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java15
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java7
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java11
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java14
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java22
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java10
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java15
108 files changed, 2963 insertions, 2091 deletions
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index 01a4b576..ba66649b 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -274,7 +274,7 @@ public class ConfigurationKeys {
*
* For any class with an {@code @ToString} annotation which extends a class other than {@code java.lang.Object}, should a call to superclass's implementation of {@code toString} be included in the generated method? (Default = skip)
*/
- public static final ConfigurationKey<CallSuperType> TO_STRING_CALL_SUPER = new ConfigurationKey<CallSuperType>("lombok.toString.callSuper", "When generating toString for classes that extend something (other than Object), either automatically take into account superclass implementation (call), or don't (skip), or warn and don't (warn). (default = warn).") {};
+ public static final ConfigurationKey<CallSuperType> TO_STRING_CALL_SUPER = new ConfigurationKey<CallSuperType>("lombok.toString.callSuper", "When generating toString for classes that extend something (other than Object), either automatically take into account superclass implementation (call), or don't (skip), or warn and don't (warn). (default = skip).") {};
/**
* lombok configuration: {@code lombok.toString.flagUsage} = {@code WARNING} | {@code ERROR}.
diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java
index 6805d214..279e6e3d 100644
--- a/src/core/lombok/EqualsAndHashCode.java
+++ b/src/core/lombok/EqualsAndHashCode.java
@@ -71,6 +71,14 @@ public @interface EqualsAndHashCode {
* @return If {@code true}, always use direct field access instead of calling the getter method.
*/
boolean doNotUseGetters() default false;
+
+ /**
+ * Determines how the result of the {@code hashCode} method will be cached.
+ * <strong>default: {@link CacheStrategy#NEVER}</strong>
+ *
+ * @return The {@code hashCode} cache strategy to be used.
+ */
+ CacheStrategy cacheStrategy() default CacheStrategy.NEVER;
/**
* Any annotations listed here are put on the generated parameter of {@code equals} and {@code canEqual}.
@@ -132,4 +140,19 @@ public @interface EqualsAndHashCode {
*/
int rank() default 0;
}
+
+ public enum CacheStrategy {
+ /**
+ * Never cache. Perform the calculation every time the method is called.
+ */
+ NEVER,
+ /**
+ * Cache the result of the first invocation of {@code hashCode} and use it for subsequent invocations.
+ * This can improve performance if all fields used for calculating the {@code hashCode} are immutable
+ * and thus every invocation of {@code hashCode} will always return the same value.
+ * <strong>Do not use this if there's <em>any</em> chance that different invocations of {@code hashCode}
+ * might return different values.</strong>
+ */
+ LAZY
+ }
}
diff --git a/src/core/lombok/bytecode/PoolConstantsApp.java b/src/core/lombok/bytecode/PoolConstantsApp.java
index c2120cc0..65b51f17 100644
--- a/src/core/lombok/bytecode/PoolConstantsApp.java
+++ b/src/core/lombok/bytecode/PoolConstantsApp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 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
@@ -26,8 +26,7 @@ import java.util.ArrayList;
import java.util.List;
import lombok.core.LombokApp;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.zwitserloot.cmdreader.CmdReader;
import com.zwitserloot.cmdreader.Description;
@@ -36,9 +35,8 @@ import com.zwitserloot.cmdreader.Mandatory;
import com.zwitserloot.cmdreader.Sequential;
import com.zwitserloot.cmdreader.Shorthand;
-@ProviderFor(LombokApp.class)
+@Provides
public class PoolConstantsApp extends LombokApp {
-
@Override public String getAppName() {
return "Xprintpool";
}
diff --git a/src/core/lombok/bytecode/PostCompilerApp.java b/src/core/lombok/bytecode/PostCompilerApp.java
index 5f49bd81..7f2237c0 100644
--- a/src/core/lombok/bytecode/PostCompilerApp.java
+++ b/src/core/lombok/bytecode/PostCompilerApp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -33,8 +33,7 @@ import java.util.List;
import lombok.core.DiagnosticsReceiver;
import lombok.core.LombokApp;
import lombok.core.PostCompiler;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.zwitserloot.cmdreader.CmdReader;
import com.zwitserloot.cmdreader.Description;
@@ -43,7 +42,7 @@ import com.zwitserloot.cmdreader.Mandatory;
import com.zwitserloot.cmdreader.Sequential;
import com.zwitserloot.cmdreader.Shorthand;
-@ProviderFor(LombokApp.class)
+@Provides
public class PostCompilerApp extends LombokApp {
@Override public List<String> getAppAliases() {
return Arrays.asList("post", "postcompile");
diff --git a/src/core/lombok/bytecode/PreventNullAnalysisRemover.java b/src/core/lombok/bytecode/PreventNullAnalysisRemover.java
index 20572e22..14e95c46 100644
--- a/src/core/lombok/bytecode/PreventNullAnalysisRemover.java
+++ b/src/core/lombok/bytecode/PreventNullAnalysisRemover.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -27,15 +27,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
import lombok.core.DiagnosticsReceiver;
import lombok.core.PostCompilerTransformation;
+import lombok.spi.Provides;
-import org.mangosdk.spi.ProviderFor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-@ProviderFor(PostCompilerTransformation.class)
+@Provides
public class PreventNullAnalysisRemover implements PostCompilerTransformation {
@Override public byte[] applyTransformations(byte[] original, String fileName, DiagnosticsReceiver diagnostics) {
diff --git a/src/core/lombok/bytecode/SneakyThrowsRemover.java b/src/core/lombok/bytecode/SneakyThrowsRemover.java
index 037cb109..7ed3f80f 100644
--- a/src/core/lombok/bytecode/SneakyThrowsRemover.java
+++ b/src/core/lombok/bytecode/SneakyThrowsRemover.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -27,8 +27,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import lombok.core.DiagnosticsReceiver;
import lombok.core.PostCompilerTransformation;
+import lombok.spi.Provides;
-import org.mangosdk.spi.ProviderFor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
@@ -37,7 +37,7 @@ import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-@ProviderFor(PostCompilerTransformation.class)
+@Provides
public class SneakyThrowsRemover implements PostCompilerTransformation {
@Override public byte[] applyTransformations(byte[] original, String fileName, final DiagnosticsReceiver diagnostics) {
diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java
index d4a92408..28d16298 100644
--- a/src/core/lombok/core/AnnotationProcessor.java
+++ b/src/core/lombok/core/AnnotationProcessor.java
@@ -26,8 +26,9 @@ import static lombok.core.Augments.ClassLoader_lombokAlreadyAddedTo;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@@ -68,7 +69,7 @@ public class AnnotationProcessor extends AbstractProcessor {
private final List<String> delayedWarnings = new ArrayList<String>();
/**
- * This method is a simplified version of {@link lombok.javac.apt.LombokProcessor.getJavacProcessingEnvironment}
+ * This method is a simplified version of {@link lombok.javac.apt.LombokProcessor#getJavacProcessingEnvironment}
* It simply returns the processing environment, but in case of gradle incremental compilation,
* the delegate ProcessingEnvironment of the gradle wrapper is returned.
*/
@@ -83,15 +84,11 @@ public class AnnotationProcessor extends AbstractProcessor {
for (Class<?> procEnvClass = procEnv.getClass(); procEnvClass != null; procEnvClass = procEnvClass.getSuperclass()) {
try {
- Field field;
- try {
- field = Permit.getField(procEnvClass, "delegate");
- } catch (NoSuchFieldException e) {
- field = Permit.getField(procEnvClass, "processingEnv");
- }
- Object delegate = field.get(procEnv);
-
- return tryRecursivelyObtainJavacProcessingEnvironment((ProcessingEnvironment) delegate);
+ Object delegate = tryGetDelegateField(procEnvClass, procEnv);
+ if (delegate == null) delegate = tryGetProcessingEnvField(procEnvClass, procEnv);
+ if (delegate == null) delegate = tryGetProxyDelegateToField(procEnvClass, procEnv);
+
+ if (delegate != null) return tryRecursivelyObtainJavacProcessingEnvironment((ProcessingEnvironment) delegate);
} catch (final Exception e) {
// no valid delegate, try superclass
}
@@ -100,6 +97,40 @@ public class AnnotationProcessor extends AbstractProcessor {
return null;
}
+ /**
+ * Gradle incremental processing
+ */
+ private static Object tryGetDelegateField(Class<?> delegateClass, Object instance) {
+ try {
+ return Permit.getField(delegateClass, "delegate").get(instance);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Kotlin incremental processing
+ */
+ private static Object tryGetProcessingEnvField(Class<?> delegateClass, Object instance) {
+ try {
+ return Permit.getField(delegateClass, "processingEnv").get(instance);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * IntelliJ IDEA >= 2020.3
+ */
+ private static Object tryGetProxyDelegateToField(Class<?> delegateClass, Object instance) {
+ try {
+ InvocationHandler handler = Proxy.getInvocationHandler(instance);
+ return Permit.getField(handler.getClass(), "val$delegateTo").get(handler);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
static class JavacDescriptor extends ProcessorDescriptor {
private Processor processor;
@@ -143,7 +174,7 @@ public class AnnotationProcessor extends AbstractProcessor {
if (!ClassLoader_lombokAlreadyAddedTo.getAndSet(environmentClassLoader, true)) {
Method m = Permit.getMethod(environmentClassLoader.getClass(), "addURL", URL.class);
URL selfUrl = new File(ClassRootFinder.findClassRootOfClass(AnnotationProcessor.class)).toURI().toURL();
- m.invoke(environmentClassLoader, selfUrl);
+ Permit.invoke(m, environmentClassLoader, selfUrl);
}
}
@@ -188,8 +219,12 @@ public class AnnotationProcessor extends AbstractProcessor {
if (supported.length() > 0) supported.append(", ");
supported.append(proc.getName());
}
- procEnv.getMessager().printMessage(Kind.WARNING, String.format("You aren't using a compiler supported by lombok, so lombok will not work and has been disabled.\n" +
+ if (procEnv.getClass().getName().equals("com.google.turbine.processing.TurbineProcessingEnvironment")) {
+ procEnv.getMessager().printMessage(Kind.ERROR, String.format("Turbine is not currently supported by lombok."));
+ } else {
+ procEnv.getMessager().printMessage(Kind.WARNING, String.format("You aren't using a compiler supported by lombok, so lombok will not work and has been disabled.\n" +
"Your processor is: %s\nLombok supports: %s", procEnv.getClass().getName(), supported));
+ }
}
}
@@ -226,6 +261,6 @@ public class AnnotationProcessor extends AbstractProcessor {
* We just return the latest version of whatever JDK we run on. Stupid? Yeah, but it's either that or warnings on all versions but 1. Blame Joe.
*/
@Override public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.values()[SourceVersion.values().length - 1];
+ return SourceVersion.latest();
}
}
diff --git a/src/core/lombok/core/Main.java b/src/core/lombok/core/Main.java
index 47afaefd..2c9d1dcb 100644
--- a/src/core/lombok/core/Main.java
+++ b/src/core/lombok/core/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 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
@@ -30,7 +30,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
public class Main {
private static final Collection<?> HELP_SWITCHES = Collections.unmodifiableList(Arrays.asList(
@@ -46,7 +46,7 @@ public class Main {
}
}
- @ProviderFor(LombokApp.class)
+ @Provides
public static class VersionApp extends LombokApp {
@Override public String getAppName() {
return "version";
@@ -66,7 +66,7 @@ public class Main {
}
}
- @ProviderFor(LombokApp.class)
+ @Provides
public static class LicenseApp extends LombokApp {
@Override public String getAppName() {
return "license";
diff --git a/src/core/lombok/core/PostCompiler.java b/src/core/lombok/core/PostCompiler.java
index 72f4b3a2..122bb268 100644
--- a/src/core/lombok/core/PostCompiler.java
+++ b/src/core/lombok/core/PostCompiler.java
@@ -28,6 +28,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
public final class PostCompiler {
private PostCompiler() {/* prevent instantiation*/};
@@ -67,8 +68,17 @@ public final class PostCompiler {
public static OutputStream wrapOutputStream(final OutputStream originalStream, final String fileName, final DiagnosticsReceiver diagnostics) throws IOException {
if (System.getProperty("lombok.disablePostCompiler", null) != null) return originalStream;
+
+ // close() can be called more than once and should be idempotent, therefore, ensure we never transform more than once.
+ final AtomicBoolean closed = new AtomicBoolean();
+
return new ByteArrayOutputStream() {
@Override public void close() throws IOException {
+ if (closed.getAndSet(true)) {
+ originalStream.close();
+ return;
+ }
+
// no need to call super
byte[] original = toByteArray();
byte[] copy = null;
diff --git a/src/core/lombok/core/PublicApiCreatorApp.java b/src/core/lombok/core/PublicApiCreatorApp.java
index c1430c24..f45808fe 100644
--- a/src/core/lombok/core/PublicApiCreatorApp.java
+++ b/src/core/lombok/core/PublicApiCreatorApp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 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
@@ -36,10 +36,9 @@ import java.util.zip.ZipEntry;
import lombok.Lombok;
import lombok.patcher.ClassRootFinder;
+import lombok.spi.Provides;
-import org.mangosdk.spi.ProviderFor;
-
-@ProviderFor(LombokApp.class)
+@Provides
public class PublicApiCreatorApp extends LombokApp {
@Override public String getAppName() {
return "publicApi";
diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java
index 2962a8e0..af0941bb 100644
--- a/src/core/lombok/core/Version.java
+++ b/src/core/lombok/core/Version.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2019 The Project Lombok Authors.
+ * Copyright (C) 2009-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,7 +30,7 @@ public class Version {
// ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries).
// Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example.
// Official builds always end in an even number. (Since 0.10.2).
- private static final String VERSION = "1.18.13";
+ private static final String VERSION = "1.18.19";
private static final String RELEASE_NAME = "Edgy Guinea Pig";
// private static final String RELEASE_NAME = "Envious Ferret";
diff --git a/src/core/lombok/core/configuration/CheckerFrameworkVersion.java b/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
index 5805678f..c37ba91d 100644
--- a/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
+++ b/src/core/lombok/core/configuration/CheckerFrameworkVersion.java
@@ -32,9 +32,9 @@ public final class CheckerFrameworkVersion implements ConfigurationValueType {
public static final String NAME__SIDE_EFFECT_FREE = "org.checkerframework.dataflow.qual.SideEffectFree";
public static final String NAME__PURE = "org.checkerframework.dataflow.qual.Pure";
public static final String NAME__UNIQUE = "org.checkerframework.common.aliasing.qual.Unique";
- public static final String NAME__RETURNS_RECEIVER = "org.checkerframework.checker.builder.qual.ReturnsReceiver";
- public static final String NAME__NOT_CALLED = "org.checkerframework.checker.builder.qual.NotCalledMethods";
- public static final String NAME__CALLED = "org.checkerframework.checker.builder.qual.CalledMethods";
+ public static final String NAME__RETURNS_RECEIVER = "org.checkerframework.common.returnsreceiver.qual.This";
+ public static final String NAME__NOT_CALLED = "org.checkerframework.checker.calledmethods.qual.NotCalledMethods";
+ public static final String NAME__CALLED = "org.checkerframework.checker.calledmethods.qual.CalledMethods";
public static final CheckerFrameworkVersion NONE = new CheckerFrameworkVersion(0);
diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java
index 9c225fdb..8d794c8a 100644
--- a/src/core/lombok/core/configuration/ConfigurationApp.java
+++ b/src/core/lombok/core/configuration/ConfigurationApp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2020 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
@@ -41,8 +41,6 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
-import org.mangosdk.spi.ProviderFor;
-
import com.zwitserloot.cmdreader.CmdReader;
import com.zwitserloot.cmdreader.Description;
import com.zwitserloot.cmdreader.Excludes;
@@ -56,8 +54,9 @@ import com.zwitserloot.cmdreader.Shorthand;
import lombok.ConfigurationKeys;
import lombok.core.LombokApp;
import lombok.core.configuration.ConfigurationParser.Collector;
+import lombok.spi.Provides;
-@ProviderFor(LombokApp.class)
+@Provides
public class ConfigurationApp extends LombokApp {
private static final URI NO_CONFIG = URI.create("");
diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java
index 1c4437d7..19cc5a9e 100644
--- a/src/core/lombok/core/handlers/HandlerUtil.java
+++ b/src/core/lombok/core/handlers/HandlerUtil.java
@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.AllArgsConstructor;
@@ -324,7 +325,9 @@ public class HandlerUtil {
"com.fasterxml.jackson.annotation.JsonTypeInfo",
"com.fasterxml.jackson.annotation.JsonView",
"com.fasterxml.jackson.databind.annotation.JsonDeserialize",
+ "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty",
+ "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText",
}));
COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"com.fasterxml.jackson.annotation.JsonAnySetter",
@@ -756,4 +759,90 @@ public class HandlerUtil {
if (PRIMITIVE_WRAPPER_TYPE_NAME_PATTERN.matcher(typeName).matches()) return 800;
return 0;
}
+
+ private static final Pattern SECTION_FINDER = Pattern.compile("^\\s*\\**\\s*[-*][-*]+\\s*([GS]ETTER|WITH(?:ER)?)\\s*[-*][-*]+\\s*\\**\\s*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+ private static final Pattern LINE_BREAK_FINDER = Pattern.compile("(\\r?\\n)?");
+
+ public enum JavadocTag {
+ PARAM("@param(?:eter)?"),
+ RETURN("@returns?");
+
+ private Pattern pattern;
+
+ JavadocTag(String regexpFragment) {
+ pattern = Pattern.compile("\\s?^[ \\t]*\\**[ \\t]*" + regexpFragment + "(\\S|\\s)*?(?=(\\s^\\s*\\**\\s*@|\\Z))", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+ }
+ }
+
+ public static String stripLinesWithTagFromJavadoc(String javadoc, JavadocTag tag) {
+ if (javadoc == null || javadoc.isEmpty()) return javadoc;
+ return tag.pattern.matcher(javadoc).replaceAll("");
+ }
+
+ public static String stripSectionsFromJavadoc(String javadoc) {
+ if (javadoc == null || javadoc.isEmpty()) return javadoc;
+ Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
+ if (!sectionMatcher.find()) return javadoc;
+
+ return javadoc.substring(0, sectionMatcher.start());
+ }
+
+ public static String getJavadocSection(String javadoc, String sectionNameSpec) {
+ if (javadoc == null || javadoc.isEmpty()) return null;
+ String[] sectionNames = sectionNameSpec.split("\\|");
+ Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
+ Matcher lineBreakMatcher = LINE_BREAK_FINDER.matcher(javadoc);
+ int sectionStart = -1;
+ int sectionEnd = -1;
+ while (sectionMatcher.find()) {
+ boolean found = false;
+ for (String sectionName : sectionNames) if (sectionMatcher.group(1).equalsIgnoreCase(sectionName)) {
+ found = true;
+ break;
+ }
+ if (found) {
+ lineBreakMatcher.find(sectionMatcher.end());
+ sectionStart = lineBreakMatcher.end();
+ } else if (sectionStart != -1) {
+ sectionEnd = sectionMatcher.start();
+ }
+ }
+
+ if (sectionStart != -1) {
+ if (sectionEnd != -1) return javadoc.substring(sectionStart, sectionEnd);
+ return javadoc.substring(sectionStart);
+ }
+
+ return null;
+ }
+
+ private static final Pattern FIND_RETURN = Pattern.compile("^\\s*\\**\\s*@returns?\\s+.*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+
+ public static String addReturnsThisIfNeeded(String in) {
+ if (in != null && FIND_RETURN.matcher(in).find()) return in;
+
+ return addJavadocLine(in, "@return {@code this}.");
+ }
+
+ public static String addReturnsUpdatedSelfIfNeeded(String in) {
+ if (in != null && FIND_RETURN.matcher(in).find()) return in;
+
+ return addJavadocLine(in, "@return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed).");
+ }
+
+ public static String addJavadocLine(String in, String line) {
+ if (in == null) return line;
+ if (in.endsWith("\n")) return in + line + "\n";
+ return in + "\n" + line;
+ }
+
+ public static String getParamJavadoc(String methodComment, String param) {
+ if (methodComment == null || methodComment.isEmpty()) return methodComment;
+ Pattern pattern = Pattern.compile("@param " + param + " (\\S|\\s)+?(?=^ ?@)", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(methodComment);
+ if (matcher.find()) {
+ return matcher.group();
+ }
+ return null;
+ }
}
diff --git a/src/core/lombok/core/handlers/SneakyThrowsAndCleanupDependencyInfo.java b/src/core/lombok/core/handlers/SneakyThrowsAndCleanupDependencyInfo.java
index 3b6f8974..482c166b 100644
--- a/src/core/lombok/core/handlers/SneakyThrowsAndCleanupDependencyInfo.java
+++ b/src/core/lombok/core/handlers/SneakyThrowsAndCleanupDependencyInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 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
@@ -25,10 +25,9 @@ import java.util.Arrays;
import java.util.List;
import lombok.core.runtimeDependencies.RuntimeDependencyInfo;
+import lombok.spi.Provides;
-import org.mangosdk.spi.ProviderFor;
-
-@ProviderFor(RuntimeDependencyInfo.class)
+@Provides
public class SneakyThrowsAndCleanupDependencyInfo implements RuntimeDependencyInfo {
@Override public List<String> getRuntimeDependencies() {
return Arrays.asList(
diff --git a/src/core/lombok/core/runtimeDependencies/CreateLombokRuntimeApp.java b/src/core/lombok/core/runtimeDependencies/CreateLombokRuntimeApp.java
index 4d5988af..21f097d7 100644
--- a/src/core/lombok/core/runtimeDependencies/CreateLombokRuntimeApp.java
+++ b/src/core/lombok/core/runtimeDependencies/CreateLombokRuntimeApp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 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
@@ -38,8 +38,7 @@ import java.util.zip.ZipEntry;
import lombok.core.LombokApp;
import lombok.core.SpiLoadUtil;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.zwitserloot.cmdreader.CmdReader;
import com.zwitserloot.cmdreader.Description;
@@ -48,7 +47,7 @@ import com.zwitserloot.cmdreader.Mandatory;
import com.zwitserloot.cmdreader.Requires;
import com.zwitserloot.cmdreader.Shorthand;
-@ProviderFor(LombokApp.class)
+@Provides
public class CreateLombokRuntimeApp extends LombokApp {
private List<RuntimeDependencyInfo> infoObjects;
diff --git a/src/core/lombok/eclipse/EclipseAugments.java b/src/core/lombok/eclipse/EcjAugments.java
index f4583ac4..cd7173a8 100644
--- a/src/core/lombok/eclipse/EclipseAugments.java
+++ b/src/core/lombok/eclipse/EcjAugments.java
@@ -21,14 +21,21 @@
*/
package lombok.eclipse;
+import java.util.Map;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.jdt.internal.core.SourceMethod;
import lombok.core.FieldAugment;
-public final class EclipseAugments {
- private EclipseAugments() {
+public final class EcjAugments {
+ private EcjAugments() {
// Prevent instantiation
}
@@ -36,4 +43,13 @@ public final class EclipseAugments {
public static final FieldAugment<ASTNode, Boolean> ASTNode_handled = FieldAugment.augment(ASTNode.class, boolean.class, "lombok$handled");
public static final FieldAugment<ASTNode, ASTNode> ASTNode_generatedBy = FieldAugment.augment(ASTNode.class, ASTNode.class, "$generatedBy");
public static final FieldAugment<Annotation, Boolean> Annotation_applied = FieldAugment.augment(Annotation.class, boolean.class, "lombok$applied");
+ public static final FieldAugment<ICompilationUnit, Map<String, String>> CompilationUnit_javadoc = FieldAugment.augment(ICompilationUnit.class, Map.class, "$javadoc");
+
+ public static final class EclipseAugments {
+ private EclipseAugments() {
+ // Prevent instantiation
+ }
+
+ public static final FieldAugment<CompilationUnit, ConcurrentMap<String, List<SourceMethod>>> CompilationUnit_delegateMethods = FieldAugment.augment(CompilationUnit.class, ConcurrentMap.class, "$delegateMethods");
+ }
}
diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java
index 2c860e14..0036ec23 100644
--- a/src/core/lombok/eclipse/EclipseAST.java
+++ b/src/core/lombok/eclipse/EclipseAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 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
@@ -21,11 +21,8 @@
*/
package lombok.eclipse;
-import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-
import java.io.File;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
@@ -33,9 +30,9 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import lombok.Lombok;
import lombok.core.AST;
import lombok.core.LombokImmutableList;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import lombok.permit.Permit;
import org.eclipse.core.resources.ResourcesPlugin;
@@ -287,23 +284,8 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
*/
public static void addProblemToCompilationResult(char[] fileNameArray, CompilationResult result,
boolean isWarning, String message, int sourceStart, int sourceEnd) {
- try {
- EcjReflectionCheck.addProblemToCompilationResult.invoke(null, fileNameArray, result, isWarning, message, sourceStart, sourceEnd);
- } catch (NoClassDefFoundError e) {
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- } catch (IllegalAccessException e) {
- throw Lombok.sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e);
- } catch (NullPointerException e) {
- if (!"false".equals(System.getProperty("lombok.debug.reflection", "false"))) {
- e.initCause(EcjReflectionCheck.problemAddProblemToCompilationResult);
- throw e;
- }
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- }
+
+ Permit.invokeSneaky(EcjReflectionCheck.problemAddProblemToCompilationResult, EcjReflectionCheck.addProblemToCompilationResult, null, fileNameArray, result, isWarning, message, sourceStart, sourceEnd);
}
public static Annotation[] getTopLevelTypeReferenceAnnotations(TypeReference tr) {
@@ -311,14 +293,14 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
if (m == null) return null;
Annotation[][] annss = null;
try {
- annss = (Annotation[][]) m.invoke(tr);
+ annss = (Annotation[][]) Permit.invoke(m, tr);
if (annss != null) return annss[0];
} catch (Throwable ignore) {}
try {
Field f = EcjReflectionCheck.typeReferenceAnnotations;
if (f == null) return null;
- annss = (Annotation[][]) f.get(tr);
+ annss = (Annotation[][]) Permit.get(f, tr);
if (annss == null) return null;
return annss[annss.length - 1];
} catch (Throwable t) {
@@ -411,7 +393,9 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
private Collection<EclipseNode> buildFields(FieldDeclaration[] children, Annotation[][] annotations) {
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
- if (children != null) for (int i = 0; i < children.length; i++) addIfNotNull(childNodes, buildField(children[i], annotations[i]));
+ if (children != null) for (int i = 0; i < children.length; i++) {
+ addIfNotNull(childNodes, buildField(children[i], annotations[i]));
+ }
return childNodes;
}
@@ -422,7 +406,7 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
}
private EclipseNode buildField(FieldDeclaration field, Annotation[] annotations) {
- if (field instanceof Initializer) return buildInitializer((Initializer)field);
+ if (field instanceof Initializer) return buildInitializer((Initializer) field);
if (setAndGetAsHandled(field)) return null;
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
addIfNotNull(childNodes, buildTypeUse(field.type));
diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java
index 361a8d42..4f86f0a5 100644
--- a/src/core/lombok/eclipse/EclipseNode.java
+++ b/src/core/lombok/eclipse/EclipseNode.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
diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java
index 0e72fb38..8d69325e 100644
--- a/src/core/lombok/eclipse/HandlerLibrary.java
+++ b/src/core/lombok/eclipse/HandlerLibrary.java
@@ -23,7 +23,7 @@ package lombok.eclipse;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import static lombok.eclipse.EclipseAugments.ASTNode_handled;
+import static lombok.eclipse.EcjAugments.ASTNode_handled;
import java.io.IOException;
import java.lang.annotation.Annotation;
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index c70e4e5c..defe8d34 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.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
@@ -23,7 +23,7 @@ package lombok.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
-import static lombok.eclipse.EclipseAugments.*;
+import static lombok.eclipse.EcjAugments.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.EclipseReflectiveMembers.*;
import java.lang.reflect.Array;
@@ -39,6 +39,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
@@ -94,6 +95,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
@@ -121,10 +123,10 @@ import lombok.core.configuration.TypeName;
import lombok.core.debug.ProblemReporter;
import lombok.core.handlers.HandlerUtil;
import lombok.core.handlers.HandlerUtil.FieldAccess;
+import lombok.eclipse.EcjAugments;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAST;
import lombok.eclipse.EclipseNode;
-import lombok.eclipse.Java14Bits;
import lombok.experimental.Accessors;
import lombok.experimental.Tolerate;
import lombok.permit.Permit;
@@ -289,9 +291,7 @@ public class EclipseHandlerUtil {
MarkerAnnotation ann = new MarkerAnnotation(copyType(annotation.type, source), pS);
setGeneratedBy(ann, source);
ann.declarationSourceEnd = ann.sourceEnd = ann.statementEnd = pE;
- try {
- reflectSet(ANNOTATION__MEMBER_VALUE_PAIR_NAME, ann, reflect(ANNOTATION__MEMBER_VALUE_PAIR_NAME, annotation));
- } catch (Exception ignore) { /* Various eclipse versions don't have it */ }
+ copyMemberValuePairName(ann, annotation);
return ann;
}
@@ -300,9 +300,7 @@ public class EclipseHandlerUtil {
setGeneratedBy(ann, source);
ann.declarationSourceEnd = ann.sourceEnd = ann.statementEnd = pE;
ann.memberValue = copyAnnotationMemberValue(((SingleMemberAnnotation) annotation).memberValue);
- try {
- reflectSet(ANNOTATION__MEMBER_VALUE_PAIR_NAME, ann, reflect(ANNOTATION__MEMBER_VALUE_PAIR_NAME, annotation));
- } catch (Exception ignore) { /* Various eclipse versions don't have it */ }
+ copyMemberValuePairName(ann, annotation);
return ann;
}
@@ -318,15 +316,21 @@ public class EclipseHandlerUtil {
for (int i = 0; i < inPairs.length; i++) ann.memberValuePairs[i] =
new MemberValuePair(inPairs[i].name, inPairs[i].sourceStart, inPairs[i].sourceEnd, copyAnnotationMemberValue(inPairs[i].value));
}
- try {
- reflectSet(ANNOTATION__MEMBER_VALUE_PAIR_NAME, ann, reflect(ANNOTATION__MEMBER_VALUE_PAIR_NAME, annotation));
- } catch (Exception ignore) { /* Various eclipse versions don't have it */ }
+ copyMemberValuePairName(ann, annotation);
return ann;
}
return annotation;
}
+ private static void copyMemberValuePairName(Annotation source, Annotation target) {
+ if (ANNOTATION__MEMBER_VALUE_PAIR_NAME == null) return;
+
+ try {
+ reflectSet(ANNOTATION__MEMBER_VALUE_PAIR_NAME, source, reflect(ANNOTATION__MEMBER_VALUE_PAIR_NAME, target));
+ } catch (Exception ignore) { /* Various eclipse versions don't have it */ }
+ }
+
static class EclipseReflectiveMembers {
public static final Field STRING_LITERAL__LINE_NUMBER;
public static final Field ANNOTATION__MEMBER_VALUE_PAIR_NAME;
@@ -372,7 +376,7 @@ public class EclipseHandlerUtil {
private static Class<?> getClass(String fqn) {
try {
return Class.forName(fqn);
- } catch (Exception e) {
+ } catch (Throwable t) {
return null;
}
}
@@ -380,7 +384,7 @@ public class EclipseHandlerUtil {
private static Field getField(Class<?> c, String fName) {
try {
return Permit.getField(c, fName);
- } catch (Exception e) {
+ } catch (Throwable t) {
return null;
}
}
@@ -775,10 +779,9 @@ public class EclipseHandlerUtil {
public static boolean hasNonNullAnnotations(EclipseNode node) {
for (EclipseNode child : node.down()) {
- if (child.getKind() == Kind.ANNOTATION) {
- Annotation annotation = (Annotation) child.get();
- for (String bn : NONNULL_ANNOTATIONS) if (typeMatches(bn, node, annotation.type)) return true;
- }
+ if (child.getKind() != Kind.ANNOTATION) continue;
+ Annotation annotation = (Annotation) child.get();
+ for (String bn : NONNULL_ANNOTATIONS) if (typeMatches(bn, node, annotation.type)) return true;
}
return false;
}
@@ -1873,15 +1876,12 @@ public class EclipseHandlerUtil {
public static MemberExistsResult constructorExists(EclipseNode node) {
node = upToTypeNode(node);
if (node != null && node.get() instanceof TypeDeclaration) {
- TypeDeclaration typeDecl = (TypeDeclaration)node.get();
+ TypeDeclaration typeDecl = (TypeDeclaration) node.get();
if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) {
- if (def instanceof ConstructorDeclaration) {
- if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
-
- if (isTolerate(node, def)) continue;
-
- return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
- }
+ if (!(def instanceof ConstructorDeclaration)) continue;
+ if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
+ if (isTolerate(node, def)) continue;
+ return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
}
@@ -1889,24 +1889,19 @@ public class EclipseHandlerUtil {
}
/**
- * Checks if there is a constructor generated by lombok.
+ * Checks if there is at least one constructor that is generated by lombok.
*
* @param node Any node that represents the Type (TypeDeclaration) to look in, or any child node thereof.
*/
public static boolean lombokConstructorExists(EclipseNode node) {
node = upToTypeNode(node);
if (node != null && node.get() instanceof TypeDeclaration) {
- TypeDeclaration typeDecl = (TypeDeclaration)node.get();
+ TypeDeclaration typeDecl = (TypeDeclaration) node.get();
if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) {
- if (def instanceof ConstructorDeclaration) {
- if ((def.bits & (ASTNode.IsDefaultConstructor | Java14Bits.IsCanonicalConstructor)) != 0) continue;
-
- if (isTolerate(node, def)) continue;
-
- if (getGeneratedBy(def) != null) {
- return true;
- }
- }
+ if (!(def instanceof ConstructorDeclaration)) continue;
+ if ((def.bits & ASTNode.IsDefaultConstructor | IsCanonicalConstructor) != 0) continue;
+ if (isTolerate(node, def)) continue;
+ if (getGeneratedBy(def) != null) return true;
}
}
@@ -2331,18 +2326,10 @@ public class EclipseHandlerUtil {
public static IntLiteral makeIntLiteral(char[] token, ASTNode source) {
int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
IntLiteral result;
- try {
- if (intLiteralConstructor != null) {
- result = intLiteralConstructor.newInstance(token, pS, pE);
- } else {
- result = (IntLiteral) intLiteralFactoryMethod.invoke(null, token, pS, pE);
- }
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e.getCause());
- } catch (IllegalAccessException e) {
- throw Lombok.sneakyThrow(e);
- } catch (InstantiationException e) {
- throw Lombok.sneakyThrow(e);
+ if (intLiteralConstructor != null) {
+ result = Permit.newInstanceSneaky(intLiteralConstructor, token, pS, pE);
+ } else {
+ result = (IntLiteral) Permit.invokeSneaky(intLiteralFactoryMethod, null, token, pS, pE);
}
if (source != null) setGeneratedBy(result, source);
@@ -2496,18 +2483,7 @@ public class EclipseHandlerUtil {
}
public static NameReference createNameReference(String name, Annotation source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long)pS << 32 | pE;
-
- char[][] nameTokens = fromQualifiedName(name);
- long[] pos = new long[nameTokens.length];
- Arrays.fill(pos, p);
-
- QualifiedNameReference nameReference = new QualifiedNameReference(nameTokens, pos, pS, pE);
- nameReference.statementEnd = pE;
-
- setGeneratedBy(nameReference, source);
- return nameReference;
+ return generateQualifiedNameRef(source, fromQualifiedName(name));
}
private static long[] copy(long[] array) {
@@ -2662,39 +2638,57 @@ public class EclipseHandlerUtil {
return ref;
}
- static boolean isClass(EclipseNode typeNode) {
- return isClassAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation | Java14Bits.AccRecord);
+ public static TypeReference createTypeReference(String typeName, ASTNode source) {
+ return generateQualifiedTypeRef(source, fromQualifiedName(typeName));
}
- static boolean isClassOrEnum(EclipseNode typeNode) {
- return isClassAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | Java14Bits.AccRecord);
+ /**
+ * Returns {@code true} if the provided node is an actual class and not some other type declaration (so, not an annotation definition, interface, enum, or record).
+ */
+ public static boolean isClass(EclipseNode typeNode) {
+ return isTypeAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation | AccRecord);
}
- public static boolean isClassAndDoesNotHaveFlags(EclipseNode typeNode, long flags) {
+ /**
+ * Returns {@code true} if the provided node is an actual class or enum and not some other type declaration (so, not an annotation definition, interface, or record).
+ */
+ public static boolean isClassOrEnum(EclipseNode typeNode) {
+ return isTypeAndDoesNotHaveFlags(typeNode, ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | AccRecord);
+ }
+
+ /**
+ * Returns {@code true} if the provided node is a record declaration (so, not an annotation definition, interface, enum, or plain class).
+ */
+ public static boolean isRecord(EclipseNode typeNode) {
TypeDeclaration typeDecl = null;
if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
- return (modifiers & flags) == 0;
+ return (modifiers & AccRecord) != 0;
}
- public static boolean isRecord(EclipseNode typeNode) {
- return typeNode.getKind() == Kind.TYPE && isRecord((TypeDeclaration) typeNode.get());
+ /**
+ * Returns {@code true} If the provided node is a field declaration, and represents a field in a {@code record} declaration.
+ */
+ public static boolean isRecordField(EclipseNode fieldNode) {
+ return fieldNode.getKind() == Kind.FIELD && (((FieldDeclaration) fieldNode.get()).modifiers & AccRecord) != 0;
}
- public static boolean isRecord(TypeDeclaration typeDeclaration) {
- return (typeDeclaration.modifiers & Java14Bits.AccRecord) != 0;
+ /**
+ * Returns {@code true) if the provided node is a type declaration <em>and</em> is <strong>not</strong> of any kind indicated by the flags (the intent is to pass flags usch as `ClassFileConstants.AccEnum`).
+ */
+ static boolean isTypeAndDoesNotHaveFlags(EclipseNode typeNode, long flags) {
+ TypeDeclaration typeDecl = null;
+ if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
+ int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
+ return (modifiers & flags) == 0;
}
- public static boolean isRecordField(EclipseNode fieldNode) {
- return fieldNode.getKind() == Kind.FIELD && (((FieldDeclaration) fieldNode.get()).modifiers & Java14Bits.AccRecord) != 0;
- }
-
public static AbstractVariableDeclaration[] getRecordComponents(TypeDeclaration typeDeclaration) {
- if (!isRecord(typeDeclaration)) return null;
+ if (typeDeclaration == null || (typeDeclaration.modifiers & AccRecord) == 0) return null;
try {
return (AbstractVariableDeclaration[]) TYPE_DECLARATION_RECORD_COMPONENTS.get(typeDeclaration);
} catch (Exception e) {
- // Ignore
+ // This presumably means this isn't a JDK16 - fall through.
}
return null;
}
@@ -2707,11 +2701,154 @@ public class EclipseHandlerUtil {
if (recordComponents != null) {
int j = 0;
for (int i = 0; i < typeDeclaration.fields.length; i++) {
- if ((typeDeclaration.fields[i].modifiers & Java14Bits.AccRecord) != 0) {
+ if ((typeDeclaration.fields[i].modifiers & AccRecord) != 0) {
annotations[i] = recordComponents[j++].annotations;
}
}
}
return annotations;
}
+
+ public static String getDocComment(CompilationUnitDeclaration cud, ASTNode node) {
+ ICompilationUnit compilationUnit = cud.compilationResult.compilationUnit;
+ if (node instanceof FieldDeclaration) {
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) node;
+ char[] rawContent = CharOperation.subarray(compilationUnit.getContents(), fieldDeclaration.declarationSourceStart, fieldDeclaration.declarationSourceEnd);
+ String rawContentString = new String(rawContent);
+ int startIndex = rawContentString.indexOf("/**");
+ int endIndex = rawContentString.indexOf("*/");
+ if (startIndex != -1 && endIndex != -1) {
+ /* Remove all leading asterisks */
+ return rawContentString.substring(startIndex + 3, endIndex).replaceAll("(?m)^\\s*\\* ?", "").trim();
+ }
+ }
+ return null;
+ }
+
+ public static void setDocComment(CompilationUnitDeclaration cud, EclipseNode eclipseNode, String doc) {
+ setDocComment(cud, (TypeDeclaration) upToTypeNode(eclipseNode).get(), eclipseNode.get(), doc);
+ }
+
+ public static void setDocComment(CompilationUnitDeclaration cud, TypeDeclaration type, ASTNode node, String doc) {
+ if (doc == null) return;
+
+ Map<String, String> docs = EcjAugments.CompilationUnit_javadoc.setIfAbsent(cud.compilationResult.compilationUnit, new HashMap<String, String>());
+ if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+ String signature = getSignature(type, methodDeclaration);
+ /* Add javadoc start marker, remove trailing line break, add leading asterisks to each line, add javadoc end marker */
+ docs.put(signature, String.format("/**%n%s%n */", doc.replaceAll("$\\r?\\n", "").replaceAll("(?m)^", " * ")));
+ }
+ }
+
+ public static String getSignature(TypeDeclaration type, AbstractMethodDeclaration methodDeclaration) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(type.name);
+ sb.append(".");
+ sb.append(methodDeclaration.selector);
+ sb.append("(");
+ Argument[] arguments = methodDeclaration.arguments;
+ if (arguments != null) {
+ for (Argument argument : arguments) {
+ sb.append(String.valueOf(argument.type));
+ }
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public static enum CopyJavadoc {
+ VERBATIM {
+ @Override public String apply(final CompilationUnitDeclaration cu, final EclipseNode node) {
+ return getDocComment(cu, node.get());
+ }
+ },
+ GETTER {
+ @Override public String apply(final CompilationUnitDeclaration cu, final EclipseNode node) {
+ final ASTNode n = node.get();
+ String javadoc = getDocComment(cu, n);
+ // step 1: Check if there is a 'GETTER' section. If yes, that becomes the new method's javadoc.
+ String out = getJavadocSection(javadoc, "GETTER");
+ final boolean sectionBased = out != null;
+ if (!sectionBased) {
+ out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), JavadocTag.PARAM);
+ }
+ return out;
+ }
+ },
+ SETTER {
+ @Override public String apply(final CompilationUnitDeclaration cu, final EclipseNode node) {
+ return applySetter(cu, node, "SETTER");
+ }
+ },
+ WITH {
+ @Override public String apply(final CompilationUnitDeclaration cu, final EclipseNode node) {
+ return addReturnsUpdatedSelfIfNeeded(applySetter(cu, node, "WITH|WITHER"));
+ }
+ },
+ WITH_BY {
+ @Override public String apply(final CompilationUnitDeclaration cu, final EclipseNode node) {
+ return applySetter(cu, node, "WITHBY|WITH_BY");
+ }
+ };
+
+ public abstract String apply(final CompilationUnitDeclaration cu, final EclipseNode node);
+
+ private static String applySetter(final CompilationUnitDeclaration cu, EclipseNode node, String sectionName) {
+ final ASTNode n = node.get();
+ String javadoc = getDocComment(cu, n);
+ // step 1: Check if there is a 'SETTER' section. If yes, that becomes the new method's javadoc.
+ String out = getJavadocSection(javadoc, sectionName);
+ final boolean sectionBased = out != null;
+ if (!sectionBased) {
+ out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), JavadocTag.RETURN);
+ }
+ return shouldReturnThis(node) ? addReturnsThisIfNeeded(out) : out;
+ }
+ }
+
+ /**
+ * Copies javadoc on one node to the other.
+ *
+ * This one is a shortcut for {@link EclipseHandlerUtil#copyJavadoc(EclipseNode, ASTNode, TypeDeclaration, CopyJavadoc, boolean)}
+ * if source and target node are in the same type.
+ */
+ public static void copyJavadoc(EclipseNode from, ASTNode to, CopyJavadoc copyMode) {
+ copyJavadoc(from, to, (TypeDeclaration) upToTypeNode(from).get(), copyMode, false);
+ }
+
+ /**
+ * Copies javadoc on one node to the other.
+ *
+ * This one is a shortcut for {@link EclipseHandlerUtil#copyJavadoc(EclipseNode, ASTNode, TypeDeclaration, CopyJavadoc, boolean)}
+ * if source and target node are in the same type.
+ */
+ public static void copyJavadoc(EclipseNode from, ASTNode to, CopyJavadoc copyMode, boolean forceAddReturn) {
+ copyJavadoc(from, to, (TypeDeclaration) upToTypeNode(from).get(), copyMode, forceAddReturn);
+ }
+
+ public static void copyJavadoc(EclipseNode from, ASTNode to, TypeDeclaration type, CopyJavadoc copyMode) {
+ copyJavadoc(from, to, type, copyMode, false);
+ }
+
+ /**
+ * Copies javadoc on one node to the other.
+ *
+ * in 'GETTER' copyMode, first a 'GETTER' segment is searched for. If it exists, that will become the javadoc for the 'to' node, and this section is
+ * stripped out of the 'from' node. If no 'GETTER' segment is found, then the entire javadoc is taken minus any {@code @param} lines and other sections.
+ * any {@code @return} lines are stripped from 'from'.
+ *
+ * in 'SETTER' mode, stripping works similarly to 'GETTER' mode, except {@code param} are copied and stripped from the original and {@code @return} are skipped.
+ */
+ public static void copyJavadoc(EclipseNode from, ASTNode to, TypeDeclaration type, CopyJavadoc copyMode, boolean forceAddReturn) {
+ if (copyMode == null) copyMode = CopyJavadoc.VERBATIM;
+ try {
+ CompilationUnitDeclaration cud = ((CompilationUnitDeclaration) from.top().get());
+ String newJavadoc = copyMode.apply(cud, from);
+ if (forceAddReturn) {
+ newJavadoc = addReturnsThisIfNeeded(newJavadoc);
+ }
+ setDocComment(cud, type, to, newJavadoc);
+ } catch (Exception ignore) {}
+ }
}
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index 85243ec1..d099cab2 100755
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -68,6 +68,7 @@ import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.HandleBuilder.BuilderJob;
public class EclipseSingularsRecipes {
public interface TypeReferenceMaker {
@@ -258,20 +259,20 @@ public class EclipseSingularsRecipes {
* If you need more control over the return type and value, use
* {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, TypeReferenceMaker, StatementMaker)}.
*/
- public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain, AccessLevel access) {
+ public void generateMethods(final BuilderJob job, SingularData data, boolean deprecate) {
TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
@Override public TypeReference make() {
- return chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ return job.oldChain ? cloneSelfType(job.builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
}
};
StatementMaker returnStatementMaker = new StatementMaker() {
@Override public ReturnStatement make() {
- return chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ return job.oldChain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
}
};
- generateMethods(cfv, data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access);
+ generateMethods(job.checkerFramework, data, deprecate, job.builderType, job.oldFluent, returnTypeMaker, returnStatementMaker, job.accessInners);
}
/**
@@ -450,7 +451,17 @@ public class EclipseSingularsRecipes {
statements.add(0, nullCheck);
}
+ protected abstract int getTypeArgumentsCount();
+
protected abstract char[][] getEmptyMakerReceiver(String targetFqn);
protected abstract char[] getEmptyMakerSelector(String targetFqn);
+
+ public MessageSend getEmptyExpression(String targetFqn, SingularData data, EclipseNode typeNode, ASTNode source) {
+ MessageSend send = new MessageSend();
+ send.receiver = generateQualifiedNameRef(source, getEmptyMakerReceiver(targetFqn));
+ send.selector = getEmptyMakerSelector(targetFqn);
+ send.typeArguments = createTypeArgs(getTypeArgumentsCount(), false, typeNode, data.getTypeArgs());
+ return send;
+ }
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleAccessors.java b/src/core/lombok/eclipse/handlers/HandleAccessors.java
index 864ff50b..6a92dee2 100644
--- a/src/core/lombok/eclipse/handlers/HandleAccessors.java
+++ b/src/core/lombok/eclipse/handlers/HandleAccessors.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
@@ -28,11 +28,11 @@ import lombok.core.HandlerPriority;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.Accessors;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.mangosdk.spi.ProviderFor;
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@HandlerPriority(65536)
public class HandleAccessors extends EclipseAnnotationHandler<Accessors> {
@Override public void handle(AnnotationValues<Accessors> annotation, Annotation ast, EclipseNode annotationNode) {
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 5054703a..c2b73988 100755
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/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
@@ -21,11 +21,10 @@
*/
package lombok.eclipse.handlers;
-import static lombok.eclipse.Eclipse.*;
import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -75,7 +74,6 @@ import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
-import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.Builder;
@@ -84,27 +82,38 @@ import lombok.ConfigurationKeys;
import lombok.Singular;
import lombok.ToString;
import lombok.core.AST.Kind;
-import lombok.core.handlers.HandlerUtil;
-import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.core.configuration.CheckerFrameworkVersion;
+import lombok.core.handlers.HandlerUtil;
+import lombok.core.handlers.HandlerUtil.FieldAccess;
+import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseHandlerUtil.CopyJavadoc;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists;
import lombok.experimental.NonFinal;
+import lombok.spi.Provides;
-@ProviderFor(EclipseAnnotationHandler.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 EclipseAnnotationHandler<Builder> {
private HandleConstructor handleConstructor = new HandleConstructor();
- private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
- private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
+ static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
+ static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
+ static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder";
+ static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray();
+ static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
+ static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
+ static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'};
+ static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
+ static final AbstractMethodDeclaration[] EMPTY_METHODS = {};
+ static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
@@ -113,6 +122,95 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return ((Boolean) expr).booleanValue();
}
+ static class BuilderJob {
+ CheckerFrameworkVersion checkerFramework;
+ EclipseNode parentType;
+ String builderMethodName, buildMethodName;
+ boolean isStatic;
+ TypeParameter[] typeParams;
+ TypeParameter[] builderTypeParams;
+ ASTNode source;
+ EclipseNode sourceNode;
+ List<BuilderFieldData> builderFields;
+ AccessLevel accessInners, accessOuters;
+ boolean oldFluent, oldChain, toBuilder;
+
+ EclipseNode builderType;
+ String builderClassName;
+ char[] builderClassNameArr;
+
+ void setBuilderClassName(String builderClassName) {
+ this.builderClassName = builderClassName;
+ this.builderClassNameArr = builderClassName.toCharArray();
+ }
+
+ TypeParameter[] copyTypeParams() {
+ return EclipseHandlerUtil.copyTypeParams(typeParams, source);
+ }
+
+ long getPos() {
+ return ((long) source.sourceStart) << 32 | source.sourceEnd;
+ }
+
+ public TypeReference createBuilderTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, !isStatic, builderTypeParams, getPos());
+ }
+
+ public TypeReference createBuilderTypeReferenceForceStatic() {
+ return namePlusTypeParamsToTypeReference(parentType, builderClassNameArr, false, builderTypeParams, getPos());
+ }
+
+ public TypeReference createBuilderParentTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType, typeParams, getPos());
+ }
+
+ public EclipseNode getTopNode() {
+ return parentType.top();
+ }
+
+ void init(AnnotationValues<Builder> annValues, Builder ann, EclipseNode node) {
+ accessOuters = ann.access();
+ if (accessOuters == null) accessOuters = AccessLevel.PUBLIC;
+ if (accessOuters == AccessLevel.NONE) {
+ sourceNode.addError("AccessLevel.NONE is not valid here");
+ accessOuters = AccessLevel.PUBLIC;
+ }
+ accessInners = accessOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessOuters;
+
+ // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
+ oldFluent = toBoolean(annValues.getActualExpression("fluent"), true);
+ oldChain = toBoolean(annValues.getActualExpression("chain"), true);
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ setBuilderClassName(fixBuilderClassName(node, ann.builderClassName()));
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ }
+
+ static String fixBuilderClassName(EclipseNode 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;
+ return "*Builder";
+ }
+
+ MethodDeclaration createNewMethodDeclaration() {
+ return new MethodDeclaration(((CompilationUnitDeclaration) getTopNode().get()).compilationResult);
+ }
+
+ String replaceBuilderClassName(char[] name) {
+ if (builderClassName.indexOf('*') == -1) return builderClassName;
+ return builderClassName.replace("*", new String(name));
+ }
+
+ String replaceBuilderClassName(String name) {
+ return builderClassName.replace("*", name);
+ }
+ }
+
static class BuilderFieldData {
Annotation[] annotations;
TypeReference type;
@@ -147,10 +245,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return true;
}
- private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
- private static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
- private static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'};
-
private static final char[] prefixWith(char[] prefix, char[] name) {
char[] out = new char[prefix.length + name.length];
System.arraycopy(prefix, 0, out, 0, prefix.length);
@@ -159,88 +253,65 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
- handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
- CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
-
- long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
+ final String BUILDER_NODE_NOT_SUPPORTED_ERR = "@Builder is only supported on classes, records, constructors, and methods.";
- Builder builderInstance = annotation.getInstance();
- AccessLevel accessForOuters = builderInstance.access();
- if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC;
- if (builderInstance.access() == AccessLevel.NONE) {
- annotationNode.addError("AccessLevel.NONE is not valid here");
- accessForOuters = AccessLevel.PUBLIC;
- }
- AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters;
-
- // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
- boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
- boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
+ handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
+ BuilderJob job = new BuilderJob();
+ job.sourceNode = annotationNode;
+ job.source = ast;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- String builderMethodName = builderInstance.builderMethodName();
- String buildMethodName = builderInstance.buildMethodName();
- String builderClassName = builderInstance.builderClassName();
- String toBuilderMethodName = "toBuilder";
- boolean toBuilder = builderInstance.toBuilder();
+ Builder annInstance = annotation.getInstance();
+ job.init(annotation, annInstance, annotationNode);
List<char[]> typeArgsForToBuilder = null;
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
- if (builderClassName == null) builderClassName = "";
-
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
- if (!builderClassName.isEmpty()) {
- if (!checkName("builderClassName", builderClassName, annotationNode)) return;
- }
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
EclipseNode parent = annotationNode.up();
- List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- TypeReference returnType;
- TypeParameter[] typeParams;
- TypeReference[] thrownExceptions;
- char[] nameOfStaticBuilderMethod;
- EclipseNode tdParent;
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ TypeReference buildMethodReturnType;
+ TypeReference[] buildMethodThrownExceptions;
+ char[] nameOfBuilderMethod;
EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
boolean addCleaning = false;
- boolean isStatic = true;
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();
+ if (!isClass(parent) && !isRecord(parent)) {
+ annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ job.parentType = parent;
+ TypeDeclaration td = (TypeDeclaration) parent.get();
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
- for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
- Annotation[] copyableAnnotations = findCopyableAnnotations(fieldNode);
-
BuilderFieldData bfd = new BuilderFieldData();
bfd.rawName = fieldNode.getName().toCharArray();
bfd.name = removePrefixFromField(fieldNode);
bfd.builderFieldName = bfd.name;
- bfd.annotations = copyAnnotations(fd, copyableAnnotations);
+ bfd.annotations = copyAnnotations(fd, findCopyableAnnotations(fieldNode));
bfd.type = fd.type;
- bfd.singularData = getSingularData(fieldNode, ast, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, ast, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -265,24 +336,26 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX);
MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.add(fieldNode);
}
- if (!isRecord(tdParent)) {
- handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
+ if (!isRecord(parent)) {
+ // Records ship with a canonical constructor that acts as @AllArgsConstructor - just use that one.
+
+ handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
Collections.<Annotation>emptyList(), annotationNode);
}
- returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p);
- typeParams = td.typeParameters;
- thrownExceptions = null;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(td.name));
- replaceNameInBuilderClassName = false;
+ job.typeParams = job.builderTypeParams = td.typeParameters;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = null;
+ nameOfBuilderMethod = null;
+ job.setBuilderClassName(job.replaceBuilderClassName(td.name));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (parent.get() instanceof ConstructorDeclaration) {
ConstructorDeclaration cd = (ConstructorDeclaration) parent.get();
if (cd.typeParameters != null && cd.typeParameters.length > 0) {
@@ -290,21 +363,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- tdParent = parent.up();
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
- returnType = namePlusTypeParamsToTypeReference(tdParent, td.typeParameters, p);
- typeParams = td.typeParameters;
- thrownExceptions = cd.thrownExceptions;
- nameOfStaticBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(cd.selector));
- replaceNameInBuilderClassName = false;
+ job.parentType = parent.up();
+ TypeDeclaration td = (TypeDeclaration) job.parentType.get();
+ job.typeParams = job.builderTypeParams = td.typeParameters;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = cd.thrownExceptions;
+ nameOfBuilderMethod = null;
+ job.setBuilderClassName(job.replaceBuilderClassName(cd.selector));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (parent.get() instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) parent.get();
- tdParent = parent.up();
- isStatic = md.isStatic();
+ job.parentType = parent.up();
+ job.isStatic = md.isStatic();
- if (toBuilder) {
- final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
+ if (job.toBuilder) {
char[] token;
char[][] pkg = null;
if (md.returnType.dimensions() > 0) {
@@ -330,12 +402,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return;
}
- if (tdParent == null || !equals(tdParent.getName(), token)) {
+ if (job.parentType == null || !equals(job.parentType.getName(), token)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
- TypeParameter[] tpOnType = ((TypeDeclaration) tdParent.get()).typeParameters;
+ TypeParameter[] tpOnType = ((TypeDeclaration) job.parentType.get()).typeParameters;
TypeParameter[] tpOnMethod = md.typeParameters;
TypeReference[][] tpOnRet_ = null;
if (md.returnType instanceof ParameterizedSingleTypeReference) {
@@ -374,18 +446,18 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- returnType = copyType(md.returnType, ast);
- typeParams = md.typeParameters;
- thrownExceptions = md.thrownExceptions;
- nameOfStaticBuilderMethod = md.selector;
- if (replaceNameInBuilderClassName) {
- char[] token = returnTypeToBuilderClassName(annotationNode, md, typeParams);
- if (token == null)
- return;
- builderClassName = builderClassName.replace("*", new String(token));
+ job.typeParams = job.builderTypeParams = md.typeParameters;
+ buildMethodReturnType = copyType(md.returnType, ast);
+ buildMethodThrownExceptions = md.thrownExceptions;
+ nameOfBuilderMethod = md.selector;
+ if (job.builderClassName.indexOf('*') > -1) {
+ char[] token = returnTypeToBuilderClassName(annotationNode, md, job.typeParams);
+ if (token == null) return; // should not happen.
+ job.setBuilderClassName(job.replaceBuilderClassName(token));
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
}
} else {
- annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
+ annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -402,40 +474,39 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = copyAnnotations(arg, copyableAnnotations);
bfd.type = arg.type;
- bfd.singularData = getSingularData(param, ast, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(param, ast, annInstance.setterPrefix());
bfd.originalFieldNode = param;
addObtainVia(bfd, param);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
}
}
- EclipseNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, accessForOuters);
- } else {
- TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get();
- if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
+ job.builderType = findInnerClass(job.parentType, job.builderClassName);
+ if (job.builderType == null) makeBuilderClass(job);
+ else {
+ TypeDeclaration builderTypeDeclaration = (TypeDeclaration) job.builderType.get();
+ if (job.isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
annotationNode.addError("Existing Builder must be a static inner class.");
return;
- } else if (!isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) != 0) {
+ } else if (!job.isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) != 0) {
annotationNode.addError("Existing Builder must be a non-static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderType, annotationNode);
/* generate errors for @Singular BFDs that have one already defined node. */ {
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
SingularData sd = bfd.singularData;
if (sd == null) continue;
EclipseSingularizer singularizer = sd.getSingularizer();
if (singularizer == null) continue;
- if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderType, sd)) {
bfd.singularData = null;
}
}
}
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
@@ -454,64 +525,64 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- generateBuilderFields(builderType, builderFields, ast);
+ generateBuilderFields(job);
if (addCleaning) {
FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
cleanDecl.declarationSourceEnd = -1;
cleanDecl.modifiers = ClassFileConstants.AccPrivate;
cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
cleanDecl.traverse(new SetGeneratedByVisitor(ast), (MethodScope) null);
- injectFieldAndMarkGenerated(builderType, cleanDecl);
+ injectFieldAndMarkGenerated(job.builderType, cleanDecl);
}
- if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
+ if (constructorExists(job.builderType) == MemberExistsResult.NOT_EXISTS) {
ConstructorDeclaration cd = HandleConstructor.createConstructor(
- AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), false,
+ AccessLevel.PACKAGE, job.builderType, Collections.<EclipseNode>emptyList(), false,
annotationNode, Collections.<Annotation>emptyList());
- if (cd != null) injectMethod(builderType, cd);
+ if (cd != null) injectMethod(job.builderType, cd);
}
- for (BuilderFieldData bfd : builderFields) {
- makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode, builderInstance.setterPrefix());
+ for (BuilderFieldData bfd : job.builderFields) {
+ makePrefixedSetterMethodsForBuilder(job, bfd, annInstance.setterPrefix());
}
{
- MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1);
- if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0);
+ MemberExistsResult methodExists = methodExists(job.buildMethodName, job.builderType, -1);
+ if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(job.buildMethodName, job.builderType, 0);
if (methodExists == MemberExistsResult.NOT_EXISTS) {
- MethodDeclaration md = generateBuildMethod(cfv, tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, accessForInners);
- if (md != null) injectMethod(builderType, md);
+ MethodDeclaration md = generateBuildMethod(job, nameOfBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning);
+ if (md != null) injectMethod(job.builderType, md);
}
}
- if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
+ if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) {
List<Included<EclipseNode, ToString.Include>> fieldNodes = new ArrayList<Included<EclipseNode, ToString.Include>>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
for (EclipseNode f : bfd.createdFields) {
fieldNodes.add(new Included<EclipseNode, ToString.Include>(f, null, true, false));
}
}
- MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
- if (md != null) injectMethod(builderType, md);
+ MethodDeclaration md = HandleToString.createToString(job.builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
+ if (md != null) injectMethod(job.builderType, md);
}
if (addCleaning) {
- MethodDeclaration cleanMethod = generateCleanMethod(builderFields, builderType, ast);
- if (cleanMethod != null) injectMethod(builderType, cleanMethod);
+ MethodDeclaration cleanMethod = generateCleanMethod(job);
+ if (cleanMethod != null) injectMethod(job.builderType, cleanMethod);
}
- if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- MethodDeclaration md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast, accessForOuters);
- if (md != null) injectMethod(tdParent, md);
+ MethodDeclaration md = generateBuilderMethod(job);
+ if (md != null) injectMethod(job.parentType, md);
}
- if (toBuilder) switch (methodExists(toBuilderMethodName, tdParent, 0)) {
+ if (job.toBuilder) switch (methodExists(TO_BUILDER_METHOD_NAME_STRING, job.parentType, 0)) {
case EXISTS_BY_USER:
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
break;
case NOT_EXISTS:
- TypeParameter[] tps = typeParams;
+ TypeParameter[] tps = job.typeParams;
if (typeArgsForToBuilder != null) {
tps = new TypeParameter[typeArgsForToBuilder.size()];
for (int i = 0; i < tps.length; i++) {
@@ -519,9 +590,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
tps[i].name = typeArgsForToBuilder.get(i);
}
}
- MethodDeclaration md = generateToBuilderMethod(cfv, isStatic, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix());
+ MethodDeclaration md = generateToBuilderMethod(job, tps, annInstance.setterPrefix());
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(job.parentType, md);
}
if (nonFinalNonDefaultedFields != null && generateBuilderMethod) {
@@ -530,7 +601,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
}
-
+
static char[] returnTypeToBuilderClassName(EclipseNode annotationNode, MethodDeclaration md, TypeParameter[] typeParams) {
char[] token;
if (md.returnType instanceof QualifiedTypeReference) {
@@ -560,26 +631,31 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return token;
}
- private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
- private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access, String prefix) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long) pS << 32 | pE;
+ private MethodDeclaration generateToBuilderMethod(BuilderJob job, TypeParameter[] typeParameters, String prefix) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
+ long p = job.getPos();
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
- out.selector = methodName.toCharArray();
- out.modifiers = toEclipseModifier(access);
+ MethodDeclaration out = job.createNewMethodDeclaration();
+ out.selector = TO_BUILDER_METHOD_NAME;
+ out.modifiers = toEclipseModifier(job.accessOuters);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- out.returnType = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p);
+
+ out.returnType = job.createBuilderTypeReference();
+ if (job.checkerFramework.generateUnique()) {
+ int len = out.returnType.getTypeName().length;
+ out.returnType.annotations = new Annotation[len][];
+ out.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
AllocationExpression invoke = new AllocationExpression();
- invoke.type = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p);
+ invoke.type = job.createBuilderTypeReference();
Expression receiver = invoke;
List<Statement> preStatements = null;
List<Statement> postStatements = null;
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
String setterName = new String(bfd.name);
- String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set";
+ String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set";
if (!setterPrefix.isEmpty()) setterName = HandlerUtil.buildAccessorName(setterPrefix, setterName);
MessageSend ms = new MessageSend();
@@ -597,13 +673,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
boolean obtainIsStatic = bfd.obtainVia.isStatic();
MessageSend obtainExpr = new MessageSend();
if (obtainIsStatic) {
- if (typeParams != null && typeParams.length > 0) {
- obtainExpr.typeArguments = new TypeReference[typeParams.length];
- for (int j = 0; j<typeParams.length; j++) {
- obtainExpr.typeArguments[j] = new SingleTypeReference(typeParams[j].name, 0);
+ if (typeParameters != null && typeParameters.length > 0) {
+ obtainExpr.typeArguments = new TypeReference[typeParameters.length];
+ for (int j = 0; j < typeParameters.length; j++) {
+ obtainExpr.typeArguments[j] = new SingleTypeReference(typeParameters[j].name, 0);
}
}
- obtainExpr.receiver = generateNameReference(type, 0);
+ obtainExpr.receiver = generateNameReference(job.parentType, 0);
} else {
obtainExpr.receiver = new ThisReference(0, 0);
}
@@ -616,7 +692,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
// for ecj so we match what javac's handler does.
LocalDeclaration ld = new LocalDeclaration(bfd.name, 0, 0);
ld.modifiers = ClassFileConstants.AccFinal;
- ld.type = EclipseHandlerUtil.copyType(bfd.type, source);
+ ld.type = EclipseHandlerUtil.copyType(bfd.type, job.source);
ld.initialization = obtainExpr;
if (preStatements == null) preStatements = new ArrayList<Statement>();
preStatements.add(ld);
@@ -645,7 +721,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
LocalDeclaration b = new LocalDeclaration(BUILDER_TEMP_VAR, pS, pE);
out.statements[preSs] = b;
b.modifiers |= ClassFileConstants.AccFinal;
- b.type = namePlusTypeParamsToTypeReference(type, builderClassName.toCharArray(), !isStatic, typeParams, p);
+ b.type = job.createBuilderTypeReference();
b.type.sourceStart = pS; b.type.sourceEnd = pE;
b.initialization = receiver;
out.statements[preSs + postSs + 1] = new ReturnStatement(new SingleNameReference(BUILDER_TEMP_VAR, p), pS, pE);
@@ -655,69 +731,81 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
out.statements[preSs] = new ReturnStatement(receiver, pS, pE);
}
- if (cfv.generateUnique()) {
- out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
- }
-
- createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
+ createRelevantNonNullAnnotation(job.parentType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope);
return out;
}
- private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) {
+ private MethodDeclaration generateCleanMethod(BuilderJob job) {
List<Statement> statements = new ArrayList<Statement>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, builderType, statements);
+ bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, job.builderType, statements);
}
}
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
thisUnclean.receiver = new ThisReference(0, 0);
statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
- MethodDeclaration decl = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ MethodDeclaration decl = job.createNewMethodDeclaration();
decl.selector = CLEAN_METHOD_NAME;
decl.modifiers = ClassFileConstants.AccPrivate;
decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
decl.statements = statements.toArray(new Statement[0]);
- decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ decl.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return decl;
}
- static Receiver generateBuildReceiver(CheckerFrameworkVersion cfv, EclipseNode type, List<BuilderFieldData> builderFields, ASTNode source) {
- if (!cfv.generateCalledMethods()) return null;
+ static Receiver generateNotCalledReceiver(BuilderJob job, String setterName) {
+ char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
+ SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(job.source, nameNotCalled.length)), job.source.sourceStart);
+ ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
+
+ TypeReference typeReference = job.createBuilderTypeReference();
+ int trLen = typeReference.getTypeName().length;
+ typeReference.annotations = new Annotation[trLen][];
+ typeReference.annotations[trLen - 1] = new Annotation[] {ann};
+ return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, 0);
+ }
+
+ static Receiver generateBuildReceiver(BuilderJob job) {
+ if (!job.checkerFramework.generateCalledMethods()) return null;
List<char[]> mandatories = new ArrayList<char[]>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name);
}
if (mandatories.size() == 0) return null;
+
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
+
char[][] nameCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__CALLED);
- SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameCalled, poss(source, nameCalled.length)), source.sourceStart);
+ SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameCalled, poss(job.source, nameCalled.length)), pS);
if (mandatories.size() == 1) {
ann.memberValue = new StringLiteral(mandatories.get(0), 0, 0, 0);
} else {
ArrayInitializer arr = new ArrayInitializer();
- arr.sourceStart = source.sourceStart;
- arr.sourceEnd = source.sourceEnd;
+ arr.sourceStart = pS;
+ arr.sourceEnd = pE;
arr.expressions = new Expression[mandatories.size()];
for (int i = 0; i < arr.expressions.length; i++) {
- arr.expressions[i] = new StringLiteral(mandatories.get(i), source.sourceStart, source.sourceEnd, 0);
+ arr.expressions[i] = new StringLiteral(mandatories.get(i), pS, pE, 0);
}
ann.memberValue = arr;
}
-
- QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(type, source.sourceStart);
- typeReference.annotations = new Annotation[typeReference.tokens.length][];
- typeReference.annotations[0] = new Annotation[] {ann};
- return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL);
+
+ TypeReference typeReference = job.createBuilderTypeReference();
+ int len = typeReference.getTypeName().length;
+ typeReference.annotations = new Annotation[len][];
+ typeReference.annotations[len - 1] = new Annotation[] {ann};
+ return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, 0);
}
- public MethodDeclaration generateBuildMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, AccessLevel access) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ public MethodDeclaration generateBuildMethod(BuilderJob job, char[] staticName, TypeReference returnType, TypeReference[] thrownExceptions, boolean addCleaning) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
@@ -730,14 +818,14 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
statements.add(new IfStatement(notClean, invokeClean, 0, 0));
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.builderFieldName, "this");
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, job.builderType, statements, bfd.builderFieldName, "this");
}
}
List<Expression> args = new ArrayList<Expression>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.nameOfSetFlag != null) {
LocalDeclaration ld = new LocalDeclaration(bfd.builderFieldName, 0, 0);
ld.type = copyType(bfd.type);
@@ -747,11 +835,11 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
statements.add(ld);
MessageSend inv = new MessageSend();
- inv.sourceStart = source.sourceStart;
- inv.sourceEnd = source.sourceEnd;
- inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L);
+ inv.sourceStart = job.source.sourceStart;
+ inv.sourceEnd = job.source.sourceEnd;
+ inv.receiver = new SingleNameReference(((TypeDeclaration) job.parentType.get()).name, 0L);
inv.selector = bfd.nameOfDefaultProvider;
- inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
+ inv.typeArguments = typeParameterNames(((TypeDeclaration) job.builderType.get()).typeParameters);
Assignment defaultAssign = new Assignment(new SingleNameReference(bfd.builderFieldName, 0L), inv, 0);
FieldReference thisSet = new FieldReference(bfd.nameOfSetFlag, 0L);
@@ -775,8 +863,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0));
}
- out.modifiers = toEclipseModifier(access);
- out.selector = name.toCharArray();
+ out.modifiers = toEclipseModifier(job.accessInners);
+ out.selector = job.buildMethodName.toCharArray();
out.thrownExceptions = copyTypes(thrownExceptions);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = returnType;
@@ -789,13 +877,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
} else {
MessageSend invoke = new MessageSend();
invoke.selector = staticName;
- if (isStatic) {
- invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0);
+ if (job.isStatic) {
+ invoke.receiver = new SingleNameReference(job.builderType.up().getName().toCharArray(), 0);
} else {
- invoke.receiver = new QualifiedThisReference(generateTypeReference(type.up(), 0) , 0, 0);
+ invoke.receiver = new QualifiedThisReference(generateTypeReference(job.builderType.up(), 0) , 0, 0);
}
- invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
+ invoke.typeArguments = typeParameterNames(((TypeDeclaration) job.builderType.get()).typeParameters);
invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[0]);
if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) {
statements.add(invoke);
@@ -804,12 +892,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
- if (cfv.generateSideEffectFree()) {
- out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
+ if (job.checkerFramework.generateSideEffectFree()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
}
- out.receiver = generateBuildReceiver(cfv, type, builderFields, source);
- if (staticName == null) createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.receiver = generateBuildReceiver(job);
+ if (staticName == null) createRelevantNonNullAnnotation(job.builderType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
@@ -840,57 +928,55 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return out;
}
- public MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long) pS << 32 | pE;
- char[] builderClassName_ = builderClassName.toCharArray();
+ public MethodDeclaration generateBuilderMethod(BuilderJob job) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
+ long p = job.getPos();
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
- out.selector = builderMethodName.toCharArray();
- out.modifiers = toEclipseModifier(access);
- if (isStatic) out.modifiers |= ClassFileConstants.AccStatic;
+ MethodDeclaration out = job.createNewMethodDeclaration();
+ out.selector = job.builderMethodName.toCharArray();
+ out.modifiers = toEclipseModifier(job.accessOuters);
+ if (job.isStatic) out.modifiers |= ClassFileConstants.AccStatic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- out.returnType = namePlusTypeParamsToTypeReference(type, builderClassName_, !isStatic, typeParams, p);
- out.typeParameters = copyTypeParams(typeParams, source);
+ out.returnType = job.createBuilderTypeReference();
+ if (job.checkerFramework.generateUnique()) {
+ int len = out.returnType.getTypeName().length;
+ out.returnType.annotations = new Annotation[len][];
+ out.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
+ out.typeParameters = job.copyTypeParams();
AllocationExpression invoke = new AllocationExpression();
- if (isStatic) {
- invoke.type = namePlusTypeParamsToTypeReference(type, builderClassName_, false, typeParams, p);
+ if (job.isStatic) {
+ invoke.type = job.createBuilderTypeReferenceForceStatic();
out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
} else {
// return this.new Builder();
QualifiedAllocationExpression qualifiedInvoke = new QualifiedAllocationExpression();
qualifiedInvoke.enclosingInstance = new ThisReference(pS, pE);
- if (typeParams == null || typeParams.length == 0) {
- qualifiedInvoke.type = new SingleTypeReference(builderClassName_, p);
+ if (job.typeParams == null || job.typeParams.length == 0) {
+ qualifiedInvoke.type = new SingleTypeReference(job.builderClassNameArr, p);
} else {
- qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, builderClassName_, false, typeParams, p);
+ qualifiedInvoke.type = namePlusTypeParamsToTypeReference(null, job.builderClassNameArr, false, job.typeParams, p);
}
out.statements = new Statement[] {new ReturnStatement(qualifiedInvoke, pS, pE)};
}
- Annotation uniqueAnn = cfv.generateUnique() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) : null;
- Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) : null;
- if (uniqueAnn != null && sefAnn != null) {
- out.annotations = new Annotation[] {uniqueAnn, sefAnn};
- } else if (uniqueAnn != null) {
- out.annotations = new Annotation[] {uniqueAnn};
- } else if (sefAnn != null) {
- out.annotations = new Annotation[] {sefAnn};
+ if (job.checkerFramework.generateSideEffectFree()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
}
- createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
+ createRelevantNonNullAnnotation(job.builderType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.builderType.get()).scope);
return out;
}
- public void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) {
+ public void generateBuilderFields(BuilderJob job) {
List<EclipseNode> existing = new ArrayList<EclipseNode>();
- for (EclipseNode child : builderType.down()) {
+ for (EclipseNode child : job.builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
+ bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, job.builderType));
} else {
EclipseNode field = null, setFlag = null;
for (EclipseNode exists : existing) {
@@ -904,45 +990,43 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = copyType(bfd.type);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- field = injectFieldAndMarkGenerated(builderType, fd);
+ fd.traverse(new SetGeneratedByVisitor(job.source), (MethodScope) null);
+ field = injectFieldAndMarkGenerated(job.builderType, fd);
}
if (setFlag == null && bfd.nameOfSetFlag != null) {
FieldDeclaration fd = new FieldDeclaration(bfd.nameOfSetFlag, 0, 0);
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- injectFieldAndMarkGenerated(builderType, fd);
+ fd.traverse(new SetGeneratedByVisitor(job.source), (MethodScope) null);
+ injectFieldAndMarkGenerated(job.builderType, fd);
}
bfd.createdFields.add(field);
}
}
}
- private static final AbstractMethodDeclaration[] EMPTY = {};
-
- public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode, String prefix) {
+ public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) {
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- makePrefixedSetterMethodForBuilder(cfv, builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode, prefix);
+ makePrefixedSetterMethodForBuilder(job, bfd, deprecate, prefix);
} else {
- bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, fluent, chain, access);
+ bfd.singularData.getSingularizer().generateMethods(job, bfd.singularData, deprecate);
}
}
- private void makePrefixedSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode, String prefix) {
- TypeDeclaration td = (TypeDeclaration) builderType.get();
+ private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData bfd, boolean deprecate, String prefix) {
+ TypeDeclaration td = (TypeDeclaration) job.builderType.get();
+ EclipseNode fieldNode = bfd.createdFields.get(0);
AbstractMethodDeclaration[] existing = td.methods;
- if (existing == null) existing = EMPTY;
+ if (existing == null) existing = EMPTY_METHODS;
int len = existing.length;
-
String setterPrefix = prefix.isEmpty() ? "set" : prefix;
String setterName;
- if(fluent) {
- setterName = prefix.isEmpty() ? new String(paramName) : HandlerUtil.buildAccessorName(setterPrefix, new String(paramName));
+ if (job.oldFluent) {
+ setterName = prefix.isEmpty() ? new String(bfd.name) : HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name));
} else {
- setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(paramName));
+ setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(bfd.name));
}
for (int i = 0; i < len; i++) {
@@ -952,34 +1036,39 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
List<Annotation> methodAnnsList = Collections.<Annotation>emptyList();
- Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
+ Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode);
if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns);
- ASTNode source = sourceNode.get();
- MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access),
- sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(source, annotations)) : Collections.<Annotation>emptyList());
- if (cfv.generateCalledMethods()) {
- char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
- SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart);
- ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
-
- QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(builderType, 0);
- typeReference.annotations = new Annotation[typeReference.tokens.length][];
- typeReference.annotations[0] = new Annotation[] {ann};
- setter.receiver = new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL);
+ ASTNode source = job.sourceNode.get();
+ MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, toEclipseModifier(job.accessInners),
+ job.sourceNode, methodAnnsList, bfd.annotations != null ? Arrays.asList(copyAnnotations(source, bfd.annotations)) : Collections.<Annotation>emptyList());
+ if (job.checkerFramework.generateCalledMethods()) setter.receiver = generateNotCalledReceiver(job, setterName);
+ if (job.sourceNode.up().getKind() == Kind.METHOD) {
+ copyJavadocFromParam(bfd.originalFieldNode.up(), setter, td, bfd.name.toString());
+ } else {
+ copyJavadoc(bfd.originalFieldNode, setter, td, CopyJavadoc.SETTER, true);
}
- injectMethod(builderType, setter);
+ injectMethod(job.builderType, setter);
+ }
+
+ private void copyJavadocFromParam(EclipseNode from, MethodDeclaration to, TypeDeclaration type, String param) {
+ try {
+ CompilationUnitDeclaration cud = (CompilationUnitDeclaration) from.top().get();
+ String methodComment = getDocComment(cud, from.get());
+ String newJavadoc = addReturnsThisIfNeeded(getParamJavadoc(methodComment, param));
+ setDocComment(cud, type, to, newJavadoc);
+ } catch (Exception ignore) {}
}
- public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source, AccessLevel access) {
- TypeDeclaration parent = (TypeDeclaration) tdParent.get();
+ public void makeBuilderClass(BuilderJob job) {
+ TypeDeclaration parent = (TypeDeclaration) job.parentType.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
- builder.modifiers |= toEclipseModifier(access);
- if (isStatic) builder.modifiers |= ClassFileConstants.AccStatic;
- builder.typeParameters = copyTypeParams(typeParams, source);
- builder.name = builderClassName.toCharArray();
- builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
- return injectType(tdParent, builder);
+ builder.modifiers |= toEclipseModifier(job.accessOuters);
+ if (job.isStatic) builder.modifiers |= ClassFileConstants.AccStatic;
+ builder.typeParameters = job.copyTypeParams();
+ builder.name = job.builderClassNameArr;
+ builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
+ job.builderType = injectType(job.parentType, builder);
}
private void addObtainVia(BuilderFieldData bfd, EclipseNode node) {
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
index d0c597fd..464a0efd 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
+++ b/src/core/lombok/eclipse/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,7 +23,6 @@ package lombok.eclipse.handlers;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.mangosdk.spi.ProviderFor;
import lombok.Builder;
import lombok.core.AST.Kind;
@@ -32,8 +31,9 @@ import lombok.core.HandlerPriority;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.SuperBuilder;
+import lombok.spi.Provides;
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@HandlerPriority(-1025) //HandleBuilder's level, minus one.
public class HandleBuilderDefault extends EclipseAnnotationHandler<Builder.Default> {
@Override public void handle(AnnotationValues<Builder.Default> annotation, Annotation ast, EclipseNode annotationNode) {
diff --git a/src/core/lombok/eclipse/handlers/HandleCleanup.java b/src/core/lombok/eclipse/handlers/HandleCleanup.java
index dde7cd08..3ce41763 100644
--- a/src/core/lombok/eclipse/handlers/HandleCleanup.java
+++ b/src/core/lombok/eclipse/handlers/HandleCleanup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -32,6 +32,7 @@ import lombok.core.AnnotationValues;
import lombok.core.AST.Kind;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -52,12 +53,11 @@ import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.Cleanup} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleCleanup extends EclipseAnnotationHandler<Cleanup> {
public void handle(AnnotationValues<Cleanup> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.CLEANUP_FLAG_USAGE, "@Cleanup");
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index ff81b763..e69c3267 100755
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2020 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -44,6 +44,7 @@ import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -79,10 +80,9 @@ 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.lookup.TypeConstants;
-import org.mangosdk.spi.ProviderFor;
public class HandleConstructor {
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleNoArgsConstructor extends EclipseAnnotationHandler<NoArgsConstructor> {
private static final String NAME = NoArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@@ -105,7 +105,7 @@ public class HandleConstructor {
}
}
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleRequiredArgsConstructor extends EclipseAnnotationHandler<RequiredArgsConstructor> {
private static final String NAME = RequiredArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@@ -166,7 +166,7 @@ public class HandleConstructor {
return fields;
}
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleAllArgsConstructor extends EclipseAnnotationHandler<AllArgsConstructor> {
private static final String NAME = AllArgsConstructor.class.getSimpleName();
@@ -456,14 +456,12 @@ public class HandleConstructor {
constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[0]);
/* Generate annotations that must be put on the generated method, and attach them. */ {
- Annotation[] constructorProperties = null, checkerFramework = null;
+ Annotation[] constructorProperties = null;
if (addConstructorProperties && !isLocalType(type)) constructorProperties = createConstructorProperties(source, fieldsToParam);
- if (getCheckerFrameworkVersion(type).generateUnique()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) };
constructor.annotations = copyAnnotations(source,
onConstructor.toArray(new Annotation[0]),
- constructorProperties,
- checkerFramework);
+ constructorProperties);
}
constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
@@ -531,6 +529,11 @@ public class HandleConstructor {
TypeDeclaration typeDecl = (TypeDeclaration) type.get();
constructor.returnType = EclipseHandlerUtil.namePlusTypeParamsToTypeReference(type, typeDecl.typeParameters, p);
constructor.annotations = null;
+ if (getCheckerFrameworkVersion(type).generateUnique()) {
+ int len = constructor.returnType.getTypeName().length;
+ constructor.returnType.annotations = new Annotation[len][];
+ constructor.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
constructor.selector = name.toCharArray();
constructor.thrownExceptions = null;
constructor.typeParameters = copyTypeParams(((TypeDeclaration) type.get()).typeParameters, source);
@@ -551,9 +554,7 @@ public class HandleConstructor {
assigns.add(nameRef);
Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
- Annotation[] checkerFramework = null;
- if (getCheckerFrameworkVersion(fieldNode).generateUnique()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE) };
- parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode), checkerFramework);
+ parameter.annotations = copyAnnotations(source, findCopyableAnnotations(fieldNode));
params.add(parameter);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java
index 6663d7d0..00e1fd38 100644
--- a/src/core/lombok/eclipse/handlers/HandleData.java
+++ b/src/core/lombok/eclipse/handlers/HandleData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -22,7 +22,7 @@
package lombok.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.*;
-import static lombok.eclipse.handlers.EclipseHandlerUtil.isClass;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.Collections;
@@ -33,14 +33,14 @@ import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.Data} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleData extends EclipseAnnotationHandler<Data> {
private HandleGetter handleGetter = new HandleGetter();
private HandleSetter handleSetter = new HandleSetter();
diff --git a/src/core/lombok/eclipse/handlers/HandleDelegate.java b/src/core/lombok/eclipse/handlers/HandleDelegate.java
index 9d352558..0e3eab66 100644
--- a/src/core/lombok/eclipse/handlers/HandleDelegate.java
+++ b/src/core/lombok/eclipse/handlers/HandleDelegate.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
@@ -27,14 +27,14 @@ import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.Delegate;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.mangosdk.spi.ProviderFor;
/**
* This class just handles basic error cases. The real meat of eclipse '@Delegate' support is in {@code PatchDelegate}.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleDelegate extends EclipseAnnotationHandler<Delegate> {
public void handle(AnnotationValues<Delegate> annotation, Annotation ast, EclipseNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.DELEGATE_FLAG_USAGE, "@Delegate");
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index 83e6de61..753c489c 100755
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.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
@@ -36,6 +36,7 @@ import java.util.Set;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.EqualsAndHashCode;
+import lombok.EqualsAndHashCode.CacheStrategy;
import lombok.core.AST.Kind;
import lombok.core.handlers.HandlerUtil;
import lombok.core.handlers.InclusionExclusionUtils;
@@ -47,6 +48,7 @@ import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -59,6 +61,8 @@ import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
@@ -86,14 +90,16 @@ import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code EqualsAndHashCode} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndHashCode> {
+ private static final String HASH_CODE_CACHE_NAME = "$hashCodeCache";
+
+ private final char[] HASH_CODE_CACHE_NAME_ARR = HASH_CODE_CACHE_NAME.toCharArray();
private final char[] PRIME = "PRIME".toCharArray();
private final char[] RESULT = "result".toCharArray();
@@ -116,7 +122,9 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
- generateMethods(annotationNode.up(), annotationNode, members, callSuper, true, fieldAccess, onParam);
+ boolean cacheHashCode = ann.cacheStrategy() == CacheStrategy.LAZY;
+
+ generateMethods(annotationNode.up(), annotationNode, members, callSuper, true, cacheHashCode, fieldAccess, onParam);
}
public void generateEqualsAndHashCodeForType(EclipseNode typeNode, EclipseNode errorNode) {
@@ -130,20 +138,18 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
- generateMethods(typeNode, errorNode, members, null, false, access, new ArrayList<Annotation>());
+ generateMethods(typeNode, errorNode, members, null, false, false, access, new ArrayList<Annotation>());
}
public void generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<Included<EclipseNode, EqualsAndHashCode.Include>> members,
- Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<Annotation> onParam) {
-
- TypeDeclaration typeDecl = null;
- if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
+ Boolean callSuper, boolean whineIfExists, boolean cacheHashCode, FieldAccess fieldAccess, List<Annotation> onParam) {
if (!isClass(typeNode)) {
errorNode.addError("@EqualsAndHashCode is only supported on a class.");
return;
}
+ TypeDeclaration typeDecl = (TypeDeclaration) typeNode.get();
boolean implicitCallSuper = callSuper == null;
if (callSuper == null) {
@@ -156,30 +162,6 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
boolean isDirectDescendantOfObject = isDirectDescendantOfObject(typeNode);
- if (isDirectDescendantOfObject && callSuper) {
- errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
- return;
- }
-
- if (implicitCallSuper && !isDirectDescendantOfObject) {
- CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_CALL_SUPER);
- if (cst == null) cst = CallSuperType.WARN;
-
- switch (cst) {
- default:
- case WARN:
- errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
- callSuper = false;
- break;
- case SKIP:
- callSuper = false;
- break;
- case CALL:
- callSuper = true;
- break;
- }
- }
-
boolean isFinal = (typeDecl.modifiers & ClassFileConstants.AccFinal) != 0;
boolean needsCanEqual = !isFinal || !isDirectDescendantOfObject;
MemberExistsResult equalsExists = methodExists("equals", typeNode, 1);
@@ -208,6 +190,30 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
//fallthrough
}
+ if (isDirectDescendantOfObject && callSuper) {
+ errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
+ return;
+ }
+
+ if (implicitCallSuper && !isDirectDescendantOfObject) {
+ CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_CALL_SUPER);
+ if (cst == null) cst = CallSuperType.WARN;
+
+ switch (cst) {
+ default:
+ case WARN:
+ errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
+ callSuper = false;
+ break;
+ case SKIP:
+ callSuper = false;
+ break;
+ case CALL:
+ callSuper = true;
+ break;
+ }
+ }
+
MethodDeclaration equalsMethod = createEquals(typeNode, members, callSuper, errorNode.get(), fieldAccess, needsCanEqual, onParam);
equalsMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
injectMethod(typeNode, equalsMethod);
@@ -218,12 +224,33 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
injectMethod(typeNode, canEqualMethod);
}
- MethodDeclaration hashCodeMethod = createHashCode(typeNode, members, callSuper, errorNode.get(), fieldAccess);
+ if (cacheHashCode){
+ if (fieldExists(HASH_CODE_CACHE_NAME, typeNode) != MemberExistsResult.NOT_EXISTS) {
+ String msg = String.format("Not caching the result of hashCode: A field named %s already exists.", HASH_CODE_CACHE_NAME);
+ errorNode.addWarning(msg);
+ cacheHashCode = false;
+ } else {
+ createHashCodeCacheField(typeNode, errorNode.get());
+ }
+ }
+
+ MethodDeclaration hashCodeMethod = createHashCode(typeNode, members, callSuper, cacheHashCode, errorNode.get(), fieldAccess);
hashCodeMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
injectMethod(typeNode, hashCodeMethod);
}
+
+ private void createHashCodeCacheField(EclipseNode typeNode, ASTNode source) {
+ FieldDeclaration hashCodeCacheDecl = new FieldDeclaration(HASH_CODE_CACHE_NAME_ARR, 0, 0);
+ hashCodeCacheDecl.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccTransient;
+ hashCodeCacheDecl.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ hashCodeCacheDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
+ hashCodeCacheDecl.declarationSourceEnd = -1;
+ injectFieldAndMarkGenerated(typeNode, hashCodeCacheDecl);
+ setGeneratedBy(hashCodeCacheDecl, source);
+ setGeneratedBy(hashCodeCacheDecl.type, source);
+ }
- public MethodDeclaration createHashCode(EclipseNode type, Collection<Included<EclipseNode, EqualsAndHashCode.Include>> members, boolean callSuper, ASTNode source, FieldAccess fieldAccess) {
+ public MethodDeclaration createHashCode(EclipseNode type, Collection<Included<EclipseNode, EqualsAndHashCode.Include>> members, boolean callSuper, boolean cacheHashCode, ASTNode source, FieldAccess fieldAccess) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -234,7 +261,10 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
method.returnType = TypeReference.baseTypeReference(TypeIds.T_int, 0);
setGeneratedBy(method.returnType, source);
Annotation overrideAnnotation = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source);
- if (getCheckerFrameworkVersion(type).generateSideEffectFree()) {
+ CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(type);
+ if (cacheHashCode && checkerFramework.generatePure()) {
+ method.annotations = new Annotation[] { overrideAnnotation, generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__PURE) };
+ } else if (checkerFramework.generateSideEffectFree()) {
method.annotations = new Annotation[] { overrideAnnotation, generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
} else {
method.annotations = new Annotation[] { overrideAnnotation };
@@ -258,6 +288,22 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
}
}
+ /* if (this.$hashCodeCache != 0) return this.$hashCodeCache; */ {
+ if (cacheHashCode) {
+ FieldReference hashCodeCacheRef = new FieldReference(HASH_CODE_CACHE_NAME_ARR, p);
+ hashCodeCacheRef.receiver = new ThisReference(pS, pE);
+ setGeneratedBy(hashCodeCacheRef, source);
+ setGeneratedBy(hashCodeCacheRef.receiver, source);
+ EqualExpression cacheNotZero = new EqualExpression(hashCodeCacheRef, makeIntLiteral("0".toCharArray(), source), OperatorIds.NOT_EQUAL);
+ setGeneratedBy(cacheNotZero, source);
+ ReturnStatement returnCache = new ReturnStatement(hashCodeCacheRef, pS, pE);
+ setGeneratedBy(returnCache, source);
+ IfStatement ifStatement = new IfStatement(cacheNotZero, returnCache, pS, pE);
+ setGeneratedBy(ifStatement, source);
+ statements.add(ifStatement);
+ }
+ }
+
/* final int PRIME = X; */ {
/* Without members, PRIME isn't used, as that would trigger a 'local variable not used' warning. */
if (!isEmpty) {
@@ -292,7 +338,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
resultDecl.initialization = init;
resultDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
resultDecl.type.sourceStart = pS; resultDecl.type.sourceEnd = pE;
- if (isEmpty) resultDecl.modifiers |= Modifier.FINAL;
+ if (isEmpty && !cacheHashCode) resultDecl.modifiers |= Modifier.FINAL;
setGeneratedBy(resultDecl.type, source);
statements.add(resultDecl);
}
@@ -387,6 +433,49 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
}
}
+ /*
+ * if (result == 0) result = Integer.MIN_VALUE;
+ * this.$hashCodeCache = result;
+ *
+ */ {
+ if (cacheHashCode) {
+ SingleNameReference resultRef = new SingleNameReference(RESULT, p);
+ setGeneratedBy(resultRef, source);
+
+ EqualExpression resultIsZero = new EqualExpression(resultRef, makeIntLiteral("0".toCharArray(), source), OperatorIds.EQUAL_EQUAL);
+ setGeneratedBy(resultIsZero, source);
+
+ resultRef = new SingleNameReference(RESULT, p);
+ setGeneratedBy(resultRef, source);
+
+ FieldReference integerMinValue = new FieldReference("MIN_VALUE".toCharArray(), p);
+ integerMinValue.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_INTEGER);
+ setGeneratedBy(integerMinValue, source);
+
+ Assignment newResult = new Assignment(resultRef, integerMinValue, pE);
+ newResult.sourceStart = pS; newResult.statementEnd = newResult.sourceEnd = pE;
+ setGeneratedBy(newResult, source);
+
+ IfStatement ifStatement = new IfStatement(resultIsZero, newResult, pS, pE);
+ setGeneratedBy(ifStatement, source);
+ statements.add(ifStatement);
+
+
+ FieldReference hashCodeCacheRef = new FieldReference(HASH_CODE_CACHE_NAME_ARR, p);
+ hashCodeCacheRef.receiver = new ThisReference(pS, pE);
+ setGeneratedBy(hashCodeCacheRef, source);
+ setGeneratedBy(hashCodeCacheRef.receiver, source);
+
+ resultRef = new SingleNameReference(RESULT, p);
+ setGeneratedBy(resultRef, source);
+
+ Assignment cacheResult = new Assignment(hashCodeCacheRef, resultRef, pE);
+ cacheResult.sourceStart = pS; cacheResult.statementEnd = cacheResult.sourceEnd = pE;
+ setGeneratedBy(cacheResult, source);
+ statements.add(cacheResult);
+ }
+ }
+
/* return result; */ {
SingleNameReference resultRef = new SingleNameReference(RESULT, p);
setGeneratedBy(resultRef, source);
diff --git a/src/core/lombok/eclipse/handlers/HandleExtensionMethod.java b/src/core/lombok/eclipse/handlers/HandleExtensionMethod.java
index 8e53d873..5857780c 100644
--- a/src/core/lombok/eclipse/handlers/HandleExtensionMethod.java
+++ b/src/core/lombok/eclipse/handlers/HandleExtensionMethod.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
@@ -28,7 +28,6 @@ import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.mangosdk.spi.ProviderFor;
import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
@@ -36,9 +35,10 @@ import lombok.core.HandlerPriority;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.ExtensionMethod;
+import lombok.spi.Provides;
// This handler just does some additional error checking; the real work is done in the agent.
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@HandlerPriority(66560) // 2^16 + 2^10; we must run AFTER HandleVal which is at 2^16
public class HandleExtensionMethod extends EclipseAnnotationHandler<ExtensionMethod> {
@Override public void handle(AnnotationValues<ExtensionMethod> annotation, Annotation ast, EclipseNode annotationNode) {
diff --git a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
index 4927a8fb..5900e7ed 100644
--- a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2016 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
@@ -38,6 +38,7 @@ import lombok.eclipse.EclipseNode;
import lombok.experimental.FieldDefaults;
import lombok.experimental.NonFinal;
import lombok.experimental.PackagePrivate;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -47,12 +48,11 @@ 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.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.FieldDefaults} annotation for eclipse.
*/
-@ProviderFor(EclipseASTVisitor.class)
+@Provides(EclipseASTVisitor.class)
@HandlerPriority(-2048) //-2^11; to ensure @Value picks up on messing with the fields' 'final' state, run earlier.
public class HandleFieldDefaults extends EclipseASTAdapter {
public boolean generateFieldDefaultsForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean makeFinal, boolean checkForTypeLevelFieldDefaults) {
diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
index cee3912c..cc1a5c3f 100644
--- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
+++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2019 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
@@ -41,7 +41,6 @@ import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
@@ -54,8 +53,9 @@ import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
import lombok.experimental.FieldNameConstants;
+import lombok.spi.Provides;
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldNameConstants> {
private static final IdentifierName FIELDS = IdentifierName.valueOf("Fields");
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index 755311b1..7f8fdef2 100644
--- a/src/core/lombok/eclipse/handlers/HandleGetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleGetter.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
@@ -35,6 +35,7 @@ import java.util.Map;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.experimental.Delegate;
+import lombok.spi.Provides;
import lombok.Getter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
@@ -73,14 +74,14 @@ 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.lookup.TypeConstants;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.Getter} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleGetter extends EclipseAnnotationHandler<Getter> {
private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0];
+ private static final String GETTER_NODE_NOT_SUPPORTED_ERR = "@Getter is only supported on a class, an enum, or a field.";
public boolean generateGetterForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelGetter, List<Annotation> onMethod) {
if (checkForTypeLevelGetter) {
@@ -91,7 +92,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
}
if (!isClassOrEnum(typeNode)) {
- pos.addError("@Getter is only supported on a class, an enum, or a field.");
+ pos.addError(GETTER_NODE_NOT_SUPPORTED_ERR);
return false;
}
@@ -165,8 +166,9 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
public void createGetterForField(AccessLevel level,
EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, boolean lazy, List<Annotation> onMethod) {
+
if (fieldNode.getKind() != Kind.FIELD) {
- errorNode.addError("@Getter is only supported on a class or a field.");
+ errorNode.addError(GETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -290,6 +292,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
}
method.traverse(new SetGeneratedByVisitor(source), parent.scope);
+ copyJavadoc(fieldNode, method, CopyJavadoc.GETTER);
return method;
}
diff --git a/src/core/lombok/eclipse/handlers/HandleHelper.java b/src/core/lombok/eclipse/handlers/HandleHelper.java
index 36f53813..7977c507 100755
--- a/src/core/lombok/eclipse/handlers/HandleHelper.java
+++ b/src/core/lombok/eclipse/handlers/HandleHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2016 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -45,7 +45,6 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.mangosdk.spi.ProviderFor;
import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
@@ -53,11 +52,12 @@ import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.Helper;
+import lombok.spi.Provides;
/**
* Handles the {@code lombok.Cleanup} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleHelper extends EclipseAnnotationHandler<Helper> {
private Statement[] getStatementsFromAstNode(ASTNode node) {
if (node instanceof Block) return ((Block) node).statements;
diff --git a/src/core/lombok/eclipse/handlers/HandleJacksonized.java b/src/core/lombok/eclipse/handlers/HandleJacksonized.java
index 90ee7582..466cc338 100644
--- a/src/core/lombok/eclipse/handlers/HandleJacksonized.java
+++ b/src/core/lombok/eclipse/handlers/HandleJacksonized.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
@@ -37,7 +37,6 @@ import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
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.mangosdk.spi.ProviderFor;
import lombok.Builder;
import lombok.ConfigurationKeys;
@@ -50,13 +49,15 @@ import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;
+import lombok.spi.Provides;
/**
* This (ecj) handler deals with {@code @Jacksonized} modifying the (already
* generated) {@code @Builder} or {@code @SuperBuilder} to conform to Jackson's
* needs for builders.
*/
-@ProviderFor(EclipseAnnotationHandler.class) @HandlerPriority(-512) // Above Handle(Super)Builder's level (builders must be already generated).
+@Provides
+@HandlerPriority(-512) // Above Handle(Super)Builder's level (builders must be already generated).
public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
private static final char[][] JSON_POJO_BUILDER_ANNOTATION = Eclipse.fromQualifiedName("com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder");
diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java
index 9eae601b..df3989a4 100644
--- a/src/core/lombok/eclipse/handlers/HandleLog.java
+++ b/src/core/lombok/eclipse/handlers/HandleLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2019 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -22,11 +22,9 @@
package lombok.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
-import static lombok.eclipse.Eclipse.fromQualifiedName;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
-import java.util.Arrays;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -35,13 +33,11 @@ import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
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.mangosdk.spi.ProviderFor;
import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
@@ -52,10 +48,11 @@ import lombok.core.handlers.LoggingFramework;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
+import lombok.spi.Provides;
public class HandleLog {
private static final IdentifierName LOG = IdentifierName.valueOf("log");
-
+
private HandleLog() {
throw new UnsupportedOperationException();
}
@@ -85,14 +82,15 @@ public class HandleLog {
annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
return;
}
+
if (isRecord(owner) && !useStatic) {
annotationNode.addError("Logger fields must be static in records.");
return;
}
-
+
Object valueGuess = annotation.getValueGuess("topic");
Expression loggerTopic = (Expression) annotation.getActualExpression("topic");
-
+
if (valueGuess instanceof String && ((String) valueGuess).trim().isEmpty()) loggerTopic = null;
if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) {
annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic.");
@@ -160,19 +158,6 @@ public class HandleLog {
return fieldDecl;
}
- public static TypeReference createTypeReference(String typeName, Annotation source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long) pS << 32 | pE;
-
- char[][] typeNameTokens = fromQualifiedName(typeName);
- long[] pos = new long[typeNameTokens.length];
- Arrays.fill(pos, p);
-
- TypeReference typeReference = new QualifiedTypeReference(typeNameTokens, pos);
- setGeneratedBy(typeReference, source);
- return typeReference;
- }
-
private static final Expression[] createFactoryParameters(ClassLiteralAccess loggingType, Annotation source, List<LogFactoryParameter> parameters, Expression loggerTopic) {
Expression[] expressions = new Expression[parameters.size()];
int pS = source.sourceStart, pE = source.sourceEnd;
@@ -223,7 +208,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.apachecommons.CommonsLog} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleCommonsLog extends EclipseAnnotationHandler<lombok.extern.apachecommons.CommonsLog> {
@Override public void handle(AnnotationValues<lombok.extern.apachecommons.CommonsLog> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -234,7 +219,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.java.Log} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleJulLog extends EclipseAnnotationHandler<lombok.extern.java.Log> {
@Override public void handle(AnnotationValues<lombok.extern.java.Log> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -245,7 +230,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.log4j.Log4j} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleLog4jLog extends EclipseAnnotationHandler<lombok.extern.log4j.Log4j> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -256,7 +241,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.log4j.Log4j2} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleLog4j2Log extends EclipseAnnotationHandler<lombok.extern.log4j.Log4j2> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j2> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -267,7 +252,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.slf4j.Slf4j} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleSlf4jLog extends EclipseAnnotationHandler<lombok.extern.slf4j.Slf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.Slf4j> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -278,7 +263,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.slf4j.XSlf4j} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleXSlf4jLog extends EclipseAnnotationHandler<lombok.extern.slf4j.XSlf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.XSlf4j> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -289,7 +274,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.jbosslog.JBossLog} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleJBossLog extends EclipseAnnotationHandler<lombok.extern.jbosslog.JBossLog> {
@Override public void handle(AnnotationValues<lombok.extern.jbosslog.JBossLog> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -300,7 +285,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.flogger.Flogger} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleFloggerLog extends EclipseAnnotationHandler<lombok.extern.flogger.Flogger> {
@Override public void handle(AnnotationValues<lombok.extern.flogger.Flogger> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_FLOGGER_FLAG_USAGE, "@Flogger", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -311,7 +296,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.CustomLog} annotation for Eclipse.
*/
- @ProviderFor(EclipseAnnotationHandler.class)
+ @Provides
public static class HandleCustomLog extends EclipseAnnotationHandler<lombok.CustomLog> {
@Override public void handle(AnnotationValues<lombok.CustomLog> annotation, Annotation source, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_CUSTOM_FLAG_USAGE, "@CustomLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
diff --git a/src/core/lombok/eclipse/handlers/HandleNonNull.java b/src/core/lombok/eclipse/handlers/HandleNonNull.java
index 8dc4f4f7..27e78d32 100644
--- a/src/core/lombok/eclipse/handlers/HandleNonNull.java
+++ b/src/core/lombok/eclipse/handlers/HandleNonNull.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2019 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
@@ -47,7 +47,6 @@ import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
@@ -55,13 +54,14 @@ import lombok.NonNull;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
+import lombok.eclipse.EcjAugments;
import lombok.eclipse.EclipseAST;
import lombok.eclipse.EclipseAnnotationHandler;
-import lombok.eclipse.EclipseAugments;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists;
+import lombok.spi.Provides;
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first.
public class HandleNonNull extends EclipseAnnotationHandler<NonNull> {
private static final char[] REQUIRE_NON_NULL = "requireNonNull".toCharArray();
@@ -91,7 +91,7 @@ public class HandleNonNull extends EclipseAnnotationHandler<NonNull> {
if (isRecordField(annotationNode.up()) && !lombokConstructorExists(typeNode)) {
handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, null, SkipIfConstructorExists.NO, Collections.<Annotation>emptyList(), annotationNode);
}
- EclipseAugments.ASTNode_handled.clear(ast);
+ EcjAugments.ASTNode_handled.clear(ast);
return;
}
diff --git a/src/core/lombok/eclipse/handlers/HandlePrintAST.java b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
index 234e29b8..9cc3e1ae 100644
--- a/src/core/lombok/eclipse/handlers/HandlePrintAST.java
+++ b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -26,7 +26,6 @@ import java.io.FileNotFoundException;
import java.io.PrintStream;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.mangosdk.spi.ProviderFor;
import lombok.Lombok;
import lombok.core.AnnotationValues;
@@ -36,11 +35,12 @@ import lombok.eclipse.DeferUntilPostDiet;
import lombok.eclipse.EclipseASTVisitor;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.spi.Provides;
/**
* Handles the {@code lombok.core.PrintAST} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@DeferUntilPostDiet
@HandlerPriority(536870912) // 2^29; this handler is customarily run at the very end.
public class HandlePrintAST extends EclipseAnnotationHandler<PrintAST> {
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index 9ebbde6d..ddae21fb 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2019 The Project Lombok Authors.
+ * Copyright (C) 2009-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -38,6 +38,7 @@ import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -56,13 +57,14 @@ 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.lookup.TypeIds;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.Setter} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleSetter extends EclipseAnnotationHandler<Setter> {
+ private static final String SETTER_NODE_NOT_SUPPORTED_ERR = "@Setter is only supported on a class or a field.";
+
public boolean generateSetterForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelSetter, List<Annotation> onMethod, List<Annotation> onParam) {
if (checkForTypeLevelSetter) {
if (hasAnnotation(Setter.class, typeNode)) {
@@ -72,7 +74,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
}
if (!isClass(typeNode)) {
- pos.addError("@Setter is only supported on a class or a field.");
+ pos.addError(SETTER_NODE_NOT_SUPPORTED_ERR);
return false;
}
@@ -142,7 +144,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
ASTNode source = sourceNode.get();
if (fieldNode.getKind() != Kind.FIELD) {
- sourceNode.addError("@Setter is only supported on a class or a field.");
+ sourceNode.addError(SETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -257,6 +259,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
if (returnType != null && returnStatement != null) createRelevantNonNullAnnotation(sourceNode, method);
method.traverse(new SetGeneratedByVisitor(source), parent.scope);
+ copyJavadoc(fieldNode, method, CopyJavadoc.SETTER, returnStatement != null);
return method;
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
index 481dbcde..5f0ca3fb 100644
--- a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
+++ b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -36,6 +36,7 @@ import lombok.core.HandlerPriority;
import lombok.eclipse.DeferUntilPostDiet;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -56,12 +57,11 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.HandleSneakyThrows} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@DeferUntilPostDiet
@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it.
public class HandleSneakyThrows extends EclipseAnnotationHandler<SneakyThrows> {
diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
index 89c27fe3..4f4baecd 100644
--- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.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
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.eclipse.handlers.HandleBuilder.*;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
@@ -49,6 +50,7 @@ import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
@@ -57,13 +59,10 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.Receiver;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
-import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -76,7 +75,6 @@ import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
-import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.Builder;
@@ -99,75 +97,102 @@ import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker;
import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker;
import lombok.eclipse.handlers.HandleBuilder.BuilderFieldData;
+import lombok.eclipse.handlers.HandleBuilder.BuilderJob;
import lombok.experimental.NonFinal;
import lombok.experimental.SuperBuilder;
+import lombok.spi.Provides;
-@ProviderFor(EclipseAnnotationHandler.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 HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
- private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
- private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
- private static final char[] DEFAULT_PREFIX = "$default$".toCharArray();
- private static final char[] SET_PREFIX = "$set".toCharArray();
- private static final char[] VALUE_PREFIX = "$value".toCharArray();
private static final char[] SELF_METHOD_NAME = "self".toCharArray();
- private static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder";
- private static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray();
private static final char[] FILL_VALUES_METHOD_NAME = "$fillValuesFrom".toCharArray();
private static final char[] FILL_VALUES_STATIC_METHOD_NAME = "$fillValuesFromInstanceIntoBuilder".toCharArray();
private static final char[] INSTANCE_VARIABLE_NAME = "instance".toCharArray();
private static final String BUILDER_VARIABLE_NAME_STRING = "b";
private static final char[] BUILDER_VARIABLE_NAME = BUILDER_VARIABLE_NAME_STRING.toCharArray();
- private static final AbstractMethodDeclaration[] EMPTY_METHODS = {};
-
- @Override
- public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) {
- handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
- CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
-
- long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
+ class SuperBuilderJob extends BuilderJob {
+ void init(AnnotationValues<SuperBuilder> annValues, SuperBuilder ann, EclipseNode node) {
+ accessOuters = accessInners = AccessLevel.PUBLIC;
+ oldFluent = true;
+ oldChain = true;
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ builderClassName = fixBuilderClassName(node, "");
+ }
- SuperBuilder superbuilderAnnotation = annotation.getInstance();
+ EclipseNode builderAbstractType;
+ String builderAbstractClassName;
+ char[] builderAbstractClassNameArr;
+ EclipseNode builderImplType;
+ String builderImplClassName;
+ char[] builderImplClassNameArr;
+ private TypeParameter[] builderTypeParams_;
+ void setBuilderToImpl() {
+ builderType = builderImplType;
+ builderClassName = builderImplClassName;
+ builderClassNameArr = builderImplClassNameArr;
+ builderTypeParams = typeParams;
+ }
- String builderMethodName = superbuilderAnnotation.builderMethodName();
- String buildMethodName = superbuilderAnnotation.buildMethodName();
+ void setBuilderToAbstract() {
+ builderType = builderAbstractType;
+ builderClassName = builderAbstractClassName;
+ builderClassNameArr = builderAbstractClassNameArr;
+ builderTypeParams = builderTypeParams_;
+ }
+ }
+
+ @Override public void handle(AnnotationValues<SuperBuilder> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
+ SuperBuilderJob job = new SuperBuilderJob();
+ job.sourceNode = annotationNode;
+ job.source = ast;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
+ SuperBuilder annInstance = annotation.getInstance();
+ job.init(annotation, annInstance, annotationNode);
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
- boolean toBuilder = superbuilderAnnotation.toBuilder();
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
- EclipseNode tdParent = annotationNode.up();
+ EclipseNode parent = annotationNode.up();
- java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- TypeReference returnType;
- TypeParameter[] typeParams;
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ TypeReference buildMethodReturnType;
boolean addCleaning = false;
- if (!isClass(tdParent)) {
- annotationNode.addError("@SuperBuilder is only supported on types.");
+ List<EclipseNode> nonFinalNonDefaultedFields = null;
+
+ if (!isClass(parent)) {
+ annotationNode.addError("@SuperBuilder is only supported on classes.");
return;
}
- TypeDeclaration td = (TypeDeclaration) tdParent.get();
+
+ job.parentType = parent;
+ TypeDeclaration td = (TypeDeclaration) parent.get();
// Gather all fields of the class that should be set by the builder.
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
- List<EclipseNode> nonFinalNonDefaultedFields = null;
- boolean valuePresent = (hasAnnotation(lombok.Value.class, tdParent) || hasAnnotation("lombok.experimental.Value", tdParent));
- for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
@@ -180,7 +205,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = copyAnnotations(fd, copyableAnnotations);
bfd.type = fd.type;
- bfd.singularData = getSingularData(fieldNode, ast, superbuilderAnnotation.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, ast, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -205,21 +230,15 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX);
MethodDeclaration md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
- if (md != null) injectMethod(tdParent, md);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.add(fieldNode);
}
- // Set the names of the builder classes.
- 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];
- returnType = namePlusTypeParamsToTypeReference(tdParent, typeParams, p);
+ job.typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0];
+ buildMethodReturnType = job.createBuilderParentTypeReference();
// <C, B> are the generics for our builder.
String classGenericName = "C";
@@ -227,25 +246,41 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
// We have to make sure that the generics' names do not collide with any generics on the annotated class,
// the classname itself, or any member type name of the annotated class.
// For instance, if there are generics <B, B2, C> on the annotated class, use "C2" and "B3" for our builder.
- java.util.Set<String> usedNames = gatherUsedTypeNames(typeParams, td);
+ java.util.Set<String> usedNames = gatherUsedTypeNames(job.typeParams, td);
classGenericName = generateNonclashingNameFor(classGenericName, usedNames);
builderGenericName = generateNonclashingNameFor(builderGenericName, usedNames);
+ TypeParameter[] paddedTypeParameters; {
+ paddedTypeParameters = new TypeParameter[job.typeParams.length + 2];
+ System.arraycopy(job.typeParams, 0, paddedTypeParameters, 0, job.typeParams.length);
+
+ TypeParameter c = new TypeParameter();
+ c.name = classGenericName.toCharArray();
+ c.type = cloneSelfType(job.parentType, job.source);
+ paddedTypeParameters[paddedTypeParameters.length - 2] = c;
+
+ TypeParameter b = new TypeParameter();
+ b.name = builderGenericName.toCharArray();
+ b.type = cloneSelfType(job.parentType, job.source);
+ paddedTypeParameters[paddedTypeParameters.length - 1] = b;
+ }
+ job.builderTypeParams = job.builderTypeParams_ = paddedTypeParameters;
+
TypeReference extendsClause = td.superclass;
TypeReference superclassBuilderClass = null;
TypeReference[] typeArguments = new TypeReference[] {
new SingleTypeReference(classGenericName.toCharArray(), 0),
- new SingleTypeReference(builderGenericName.toCharArray(), 0)
+ new SingleTypeReference(builderGenericName.toCharArray(), 0),
};
if (extendsClause instanceof QualifiedTypeReference) {
QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference)extendsClause;
String superclassClassName = String.valueOf(qualifiedTypeReference.getLastToken());
- String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName);
+ String superclassBuilderClassName = job.replaceBuilderClassName(superclassClassName);
char[][] tokens = Arrays.copyOf(qualifiedTypeReference.tokens, qualifiedTypeReference.tokens.length + 1);
tokens[tokens.length-1] = superclassBuilderClassName.toCharArray();
long[] poss = new long[tokens.length];
- Arrays.fill(poss, p);
+ Arrays.fill(poss, job.getPos());
TypeReference[] superclassTypeArgs = getTypeParametersFrom(extendsClause);
@@ -261,7 +296,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
char[][] tokens = new char[][] {superClass.toCharArray(), superclassBuilderClassName.toCharArray()};
long[] poss = new long[tokens.length];
- Arrays.fill(poss, p);
+ Arrays.fill(poss, job.getPos());
TypeReference[] superclassTypeArgs = getTypeParametersFrom(extendsClause);
@@ -272,40 +307,43 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
superclassBuilderClass = new ParameterizedQualifiedTypeReference(tokens, typeArgsForTokens, 0, poss);
}
+ job.builderAbstractClassName = job.builderClassName = job.replaceBuilderClassName(td.name);
+ job.builderAbstractClassNameArr = job.builderClassNameArr = job.builderAbstractClassName.toCharArray();
+ job.builderImplClassName = job.builderAbstractClassName + "Impl";
+ job.builderImplClassNameArr = job.builderImplClassName.toCharArray();
+
// If there is no superclass, superclassBuilderClassExpression is still == null at this point.
// You can use it to check whether to inherit or not.
- if (!constructorExists(tdParent, builderClassName)) {
- generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
- superclassBuilderClass != null);
+ if (!constructorExists(parent, job.builderClassName)) {
+ generateBuilderBasedConstructor(job, superclassBuilderClass != null);
}
// Create the abstract builder class, or reuse an existing one.
- EclipseNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = generateBuilderAbstractClass(tdParent, builderClassName, superclassBuilderClass,
- typeParams, ast, classGenericName, builderGenericName);
+ job.builderAbstractType = findInnerClass(parent, job.builderClassName);
+ if (job.builderAbstractType == null) {
+ job.builderAbstractType = generateBuilderAbstractClass(job, superclassBuilderClass, classGenericName, builderGenericName);
} else {
- TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get();
+ TypeDeclaration builderTypeDeclaration = (TypeDeclaration) job.builderAbstractType.get();
if ((builderTypeDeclaration.modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract)) == 0) {
annotationNode.addError("Existing Builder must be an abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderAbstractType, annotationNode);
// Generate errors for @Singular BFDs that have one already defined node.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
SingularData sd = bfd.singularData;
if (sd == null) continue;
EclipseSingularizer singularizer = sd.getSingularizer();
if (singularizer == null) continue;
- if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderAbstractType, sd)) {
bfd.singularData = null;
}
}
}
// Check validity of @ObtainVia fields, and add check if adding cleaning for @Singular is necessary.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
@@ -325,47 +363,52 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Generate the fields in the abstract builder class that hold the values for the instance.
- generateBuilderFields(builderType, builderFields, ast);
+ job.setBuilderToAbstract();
+ generateBuilderFields(job);
if (addCleaning) {
FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
cleanDecl.declarationSourceEnd = -1;
cleanDecl.modifiers = ClassFileConstants.AccPrivate;
cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
- injectFieldAndMarkGenerated(builderType, cleanDecl);
+ injectFieldAndMarkGenerated(job.builderType, cleanDecl);
}
- if (toBuilder) {
+ if (job.toBuilder) {
// Generate $fillValuesFrom() method in the abstract builder.
- injectMethod(builderType, generateFillValuesMethod(tdParent, superclassBuilderClass != null, builderGenericName, classGenericName, builderClassName, typeParams));
+ injectMethod(job.builderType, generateFillValuesMethod(job, superclassBuilderClass != null, builderGenericName, classGenericName));
// Generate $fillValuesFromInstanceIntoBuilder() method in the builder implementation class.
- injectMethod(builderType, generateStaticFillValuesMethod(tdParent, builderClassName, typeParams, builderFields, ast, superbuilderAnnotation.setterPrefix()));
+ injectMethod(job.builderType, generateStaticFillValuesMethod(job, annInstance.setterPrefix()));
}
// Generate abstract self() and build() methods in the abstract builder.
- injectMethod(builderType, generateAbstractSelfMethod(cfv, tdParent, superclassBuilderClass != null, builderGenericName));
- injectMethod(builderType, generateAbstractBuildMethod(cfv, builderType, buildMethodName, builderFields, superclassBuilderClass != null, classGenericName, ast));
+ injectMethod(job.builderType, generateAbstractSelfMethod(job, superclassBuilderClass != null, builderGenericName));
+ job.setBuilderToAbstract();
+ injectMethod(job.builderType, generateAbstractBuildMethod(job, superclassBuilderClass != null, classGenericName));
// Create the setter methods in the abstract builder.
- for (BuilderFieldData bfd : builderFields) {
- generateSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, builderGenericName, superbuilderAnnotation.setterPrefix());
+ for (BuilderFieldData bfd : job.builderFields) {
+ generateSetterMethodsForBuilder(job, bfd, builderGenericName, annInstance.setterPrefix());
}
// Create the toString() method for the abstract builder.
- if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
+ if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) {
List<Included<EclipseNode, ToString.Include>> fieldNodes = new ArrayList<Included<EclipseNode, ToString.Include>>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
for (EclipseNode f : bfd.createdFields) {
fieldNodes.add(new Included<EclipseNode, ToString.Include>(f, null, true, false));
}
}
// Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder.
- MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, superclassBuilderClass != null, ast, FieldAccess.ALWAYS_FIELD);
+ MethodDeclaration md = HandleToString.createToString(job.builderType, fieldNodes, true, superclassBuilderClass != null, ast, FieldAccess.ALWAYS_FIELD);
if (md != null) {
- injectMethod(builderType, md);
+ injectMethod(job.builderType, md);
}
}
- if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast));
+ if (addCleaning) {
+ job.setBuilderToAbstract();
+ injectMethod(job.builderType, generateCleanMethod(job));
+ }
boolean isAbstract = (td.modifiers & ClassFileConstants.AccAbstract) != 0;
if (isAbstract) {
@@ -374,26 +417,27 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Create the builder implementation class, or reuse an existing one.
- EclipseNode builderImplType = findInnerClass(tdParent, builderImplClassName);
- if (builderImplType == null) {
- builderImplType = generateBuilderImplClass(tdParent, builderImplClassName, builderClassName, typeParams, ast);
+ job.builderImplType = findInnerClass(parent, job.builderImplClassName);
+ if (job.builderImplType == null) {
+ job.builderImplType = generateBuilderImplClass(job, job.builderImplClassName);
} else {
- TypeDeclaration builderImplTypeDeclaration = (TypeDeclaration) builderImplType.get();
+ TypeDeclaration builderImplTypeDeclaration = (TypeDeclaration) job.builderImplType.get();
if ((builderImplTypeDeclaration.modifiers & ClassFileConstants.AccAbstract) != 0 ||
(builderImplTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
annotationNode.addError("Existing BuilderImpl must be a non-abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderImplType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderImplType, annotationNode);
}
- if (toBuilder) {
+ job.setBuilderToImpl();
+ if (job.toBuilder) {
// Add the toBuilder() method to the annotated class.
- switch (methodExists(TO_BUILDER_METHOD_NAME_STRING, tdParent, 0)) {
+ switch (methodExists(TO_BUILDER_METHOD_NAME_STRING, job.parentType, 0)) {
case EXISTS_BY_USER:
break;
case NOT_EXISTS:
- injectMethod(tdParent, generateToBuilderMethod(cfv, builderClassName, builderImplClassName, tdParent, typeParams, ast));
+ injectMethod(parent, generateToBuilderMethod(job));
break;
default:
// Should not happen.
@@ -401,17 +445,19 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Create the self() and build() methods in the BuilderImpl.
- injectMethod(builderImplType, generateSelfMethod(cfv, builderImplType, typeParams, p));
+ job.setBuilderToImpl();
+ injectMethod(job.builderImplType, generateSelfMethod(job));
- if (methodExists(buildMethodName, builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
- injectMethod(builderImplType, generateBuildMethod(cfv, builderImplType, buildMethodName, returnType, builderFields, ast));
+ if (methodExists(job.buildMethodName, job.builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
+ job.setBuilderToImpl();
+ injectMethod(job.builderImplType, generateBuildMethod(job, buildMethodReturnType));
}
// Add the builder() method to the annotated class.
- if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod && methodExists(job.builderMethodName, parent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- MethodDeclaration md = generateBuilderMethod(cfv, builderMethodName, builderClassName, builderImplClassName, tdParent, typeParams, ast);
- if (md != null) injectMethod(tdParent, md);
+ MethodDeclaration md = generateBuilderMethod(job);
+ if (md != null) injectMethod(parent, md);
}
if (nonFinalNonDefaultedFields != null && generateBuilderMethod) {
@@ -421,97 +467,82 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
}
- private EclipseNode generateBuilderAbstractClass(EclipseNode tdParent, String builderClass,
- TypeReference superclassBuilderClass, TypeParameter[] typeParams,
- ASTNode source, String classGenericName, String builderGenericName) {
-
- TypeDeclaration parent = (TypeDeclaration) tdParent.get();
+ private EclipseNode generateBuilderAbstractClass(BuilderJob job, TypeReference superclassBuilderClass, String classGenericName, String builderGenericName) {
+ TypeDeclaration parent = (TypeDeclaration) job.parentType.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
builder.modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract;
- builder.name = builderClass.toCharArray();
+ builder.name = job.builderClassNameArr;
// Keep any type params of the annotated class.
- builder.typeParameters = Arrays.copyOf(copyTypeParams(typeParams, source), typeParams.length + 2);
+ builder.typeParameters = Arrays.copyOf(copyTypeParams(job.typeParams, job.source), job.typeParams.length + 2);
// Add builder-specific type params required for inheritable builders.
// 1. The return type for the build() method, named "C", which extends the annotated class.
TypeParameter o = new TypeParameter();
o.name = classGenericName.toCharArray();
- o.type = cloneSelfType(tdParent, source);
+ o.type = cloneSelfType(job.parentType, job.source);
builder.typeParameters[builder.typeParameters.length - 2] = o;
// 2. The return type for all setter methods, named "B", which extends this builder class.
o = new TypeParameter();
o.name = builderGenericName.toCharArray();
- TypeReference[] typerefs = appendBuilderTypeReferences(typeParams, classGenericName, builderGenericName);
- o.type = generateParameterizedTypeReference(tdParent, builderClass.toCharArray(), false, typerefs, 0);
+ TypeReference[] typerefs = appendBuilderTypeReferences(job.typeParams, classGenericName, builderGenericName);
+ o.type = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, typerefs, 0);
builder.typeParameters[builder.typeParameters.length - 1] = o;
- builder.superclass = copyType(superclassBuilderClass, source);
+ if (superclassBuilderClass != null) builder.superclass = copyType(superclassBuilderClass, job.source);
builder.createDefaultConstructor(false, true);
- builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
- return injectType(tdParent, builder);
+ builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
+ return injectType(job.parentType, builder);
}
- private EclipseNode generateBuilderImplClass(EclipseNode tdParent, String builderImplClass, String builderAbstractClass, TypeParameter[] typeParams, ASTNode source) {
- TypeDeclaration parent = (TypeDeclaration) tdParent.get();
+ private EclipseNode generateBuilderImplClass(BuilderJob job, String builderImplClass) {
+ TypeDeclaration parent = (TypeDeclaration) job.parentType.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
builder.modifiers |= ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal;
builder.name = builderImplClass.toCharArray();
// Add type params if there are any.
- if (typeParams != null && typeParams.length > 0) builder.typeParameters = copyTypeParams(typeParams, source);
+ if (job.typeParams != null && job.typeParams.length > 0) builder.typeParameters = copyTypeParams(job.typeParams, job.source);
- if (builderAbstractClass != null) {
+ if (job.builderClassName != null) {
// Extend the abstract builder.
// 1. Add any type params of the annotated class.
- TypeReference[] typeArgs = new TypeReference[typeParams.length + 2];
- for (int i = 0; i < typeParams.length; i++) {
- typeArgs[i] = new SingleTypeReference(typeParams[i].name, 0);
+ TypeReference[] typeArgs = new TypeReference[job.typeParams.length + 2];
+ for (int i = 0; i < job.typeParams.length; i++) {
+ typeArgs[i] = new SingleTypeReference(job.typeParams[i].name, 0);
}
// 2. The return type for the build() method (named "C" in the abstract builder), which is the annotated class.
// 3. The return type for all setter methods (named "B" in the abstract builder), which is this builder class.
- typeArgs[typeArgs.length - 2] = cloneSelfType(tdParent, source);
- typeArgs[typeArgs.length - 1] = createTypeReferenceWithTypeParameters(tdParent, builderImplClass, typeParams);
- builder.superclass = generateParameterizedTypeReference(tdParent, builderAbstractClass.toCharArray(), false, typeArgs, 0);
+ typeArgs[typeArgs.length - 2] = cloneSelfType(job.parentType, job.source);
+ typeArgs[typeArgs.length - 1] = createTypeReferenceWithTypeParameters(job.parentType, builderImplClass, job.typeParams);
+ builder.superclass = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, typeArgs, 0);
}
builder.createDefaultConstructor(false, true);
- builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
- return injectType(tdParent, builder);
+ builder.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
+ return injectType(job.parentType, builder);
}
/**
* Generates a constructor that has a builder as the only parameter.
* The values from the builder are used to initialize the fields of new instances.
*
- * @param typeNode
- * the type (with the {@code @Builder} annotation) for which a
- * constructor should be generated.
- * @param typeParams
- * @param cfv Settings for generating checker framework annotations
- * @param builderFields a list of fields in the builder which should be assigned to new instances.
- * @param source the annotation (used for setting source code locations for the generated code).
* @param callBuilderBasedSuperConstructor
* If {@code true}, the constructor will explicitly call a super
* constructor with the builder as argument. Requires
* {@code builderClassAsParameter != null}.
*/
- private void generateBuilderBasedConstructor(CheckerFrameworkVersion cfv, EclipseNode typeNode, TypeParameter[] typeParams, List<BuilderFieldData> builderFields,
- EclipseNode sourceNode, String builderClassName, boolean callBuilderBasedSuperConstructor) {
+ private void generateBuilderBasedConstructor(BuilderJob job, boolean callBuilderBasedSuperConstructor) {
+ TypeDeclaration typeDeclaration = ((TypeDeclaration) job.parentType.get());
+ long p = job.getPos();
- ASTNode source = sourceNode.get();
-
- TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
- long p = (long) source.sourceStart << 32 | source.sourceEnd;
-
- ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
+ ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) job.parentType.top().get()).compilationResult);
constructor.modifiers = toEclipseModifier(AccessLevel.PROTECTED);
- if (cfv.generateUnique()) constructor.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
constructor.selector = typeDeclaration.name;
if (callBuilderBasedSuperConstructor) {
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super);
@@ -519,21 +550,21 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
} else {
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
}
- constructor.constructorCall.sourceStart = source.sourceStart;
- constructor.constructorCall.sourceEnd = source.sourceEnd;
+ constructor.constructorCall.sourceStart = job.source.sourceStart;
+ constructor.constructorCall.sourceEnd = job.source.sourceEnd;
constructor.thrownExceptions = null;
constructor.typeParameters = null;
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
- constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
+ constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = job.source.sourceStart;
+ constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = job.source.sourceEnd;
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND)};
- TypeReference builderType = generateParameterizedTypeReference(typeNode, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p);
+ TypeReference builderType = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), p);
constructor.arguments = new Argument[] {new Argument(BUILDER_VARIABLE_NAME, p, builderType, Modifier.FINAL)};
List<Statement> statements = new ArrayList<Statement>();
- for (BuilderFieldData fieldNode : builderFields) {
+ for (BuilderFieldData fieldNode : job.builderFields) {
FieldReference fieldInThis = new FieldReference(fieldNode.rawName, p);
int s = (int) (p >> 32);
int e = (int) p;
@@ -541,7 +572,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
Expression assignmentExpr;
if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) {
- fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.builderFieldName, BUILDER_VARIABLE_NAME_STRING);
+ fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, job.parentType, statements, fieldNode.builderFieldName, BUILDER_VARIABLE_NAME_STRING);
assignmentExpr = new SingleNameReference(fieldNode.builderFieldName, p);
} else {
char[][] variableInBuilder = new char[][] {BUILDER_VARIABLE_NAME, fieldNode.builderFieldName};
@@ -557,11 +588,11 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
QualifiedNameReference setVariableInBuilderRef = new QualifiedNameReference(setVariableInBuilder, positions, s, e);
MessageSend defaultMethodCall = new MessageSend();
- defaultMethodCall.sourceStart = source.sourceStart;
- defaultMethodCall.sourceEnd = source.sourceEnd;
- defaultMethodCall.receiver = generateNameReference(typeNode, 0L);
+ defaultMethodCall.sourceStart = job.source.sourceStart;
+ defaultMethodCall.sourceEnd = job.source.sourceEnd;
+ defaultMethodCall.receiver = generateNameReference(job.parentType, 0L);
defaultMethodCall.selector = fieldNode.nameOfDefaultProvider;
- defaultMethodCall.typeArguments = typeParameterNames(((TypeDeclaration) typeNode.get()).typeParameters);
+ defaultMethodCall.typeArguments = typeParameterNames(((TypeDeclaration) job.parentType.get()).typeParameters);
Statement defaultAssignment = new Assignment(fieldInThis, defaultMethodCall, (int) p);
IfStatement ifBlockForDefault = new IfStatement(setVariableInBuilderRef, assignment, defaultAssignment, s, e);
@@ -571,41 +602,50 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
if (hasNonNullAnnotations(fieldNode.originalFieldNode)) {
- Statement nullCheck = generateNullCheck((FieldDeclaration) fieldNode.originalFieldNode.get(), sourceNode, null);
+ Statement nullCheck = generateNullCheck((FieldDeclaration) fieldNode.originalFieldNode.get(), job.sourceNode, null);
if (nullCheck != null) statements.add(nullCheck);
}
}
constructor.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
+ if (job.checkerFramework.generateSideEffectFree()) {
+ constructor.annotations = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
+ }
- constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
+ constructor.traverse(new SetGeneratedByVisitor(job.source), typeDeclaration.scope);
- injectMethod(typeNode, constructor);
+ injectMethod(job.parentType, constructor);
}
- private MethodDeclaration generateBuilderMethod(CheckerFrameworkVersion cfv, String builderMethodName, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
+ private MethodDeclaration generateBuilderMethod(SuperBuilderJob job) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
long p = (long) pS << 32 | pE;
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
- out.selector = builderMethodName.toCharArray();
+ MethodDeclaration out = job.createNewMethodDeclaration();
+ out.selector = job.builderMethodName.toCharArray();
out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
// Add type params if there are any.
- if (typeParams != null && typeParams.length > 0) out.typeParameters = copyTypeParams(typeParams, source);
+ if (job.typeParams != null && job.typeParams.length > 0) out.typeParameters = copyTypeParams(job.typeParams, job.source);
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) };
- out.returnType = generateParameterizedTypeReference(type, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p);
+ out.returnType = generateParameterizedTypeReference(job.parentType, job.builderAbstractClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), p);
+ if (job.checkerFramework.generateUnique()) {
+ int len = out.returnType.getTypeName().length;
+ out.returnType.annotations = new Annotation[len][];
+ out.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
AllocationExpression invoke = new AllocationExpression();
- invoke.type = namePlusTypeParamsToTypeReference(type, builderImplClassName.toCharArray(), false, typeParams, p);
+ invoke.type = namePlusTypeParamsToTypeReference(job.parentType, job.builderImplClassNameArr, false, job.typeParams, p);
out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
+ if (job.checkerFramework.generateSideEffectFree()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
+ }
- if (cfv.generateUnique()) out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
-
- createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
+ createRelevantNonNullAnnotation(job.parentType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope);
return out;
}
@@ -617,30 +657,36 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* }
* </pre>
*/
- private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String builderClassName, String builderImplClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
+ private MethodDeclaration generateToBuilderMethod(SuperBuilderJob job) {
+ int pS = job.source.sourceStart, pE = job.source.sourceEnd;
long p = (long) pS << 32 | pE;
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = TO_BUILDER_METHOD_NAME;
out.modifiers = ClassFileConstants.AccPublic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) };
- out.returnType = generateParameterizedTypeReference(type, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), p);
+ out.returnType = generateParameterizedTypeReference(job.parentType, job.builderAbstractClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), p);
+ if (job.checkerFramework.generateUnique()) {
+ int len = out.returnType.getTypeName().length;
+ out.returnType.annotations = new Annotation[len][];
+ out.returnType.annotations[len - 1] = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__UNIQUE)};
+ }
AllocationExpression newClass = new AllocationExpression();
- newClass.type = namePlusTypeParamsToTypeReference(type, builderImplClassName.toCharArray(), false, typeParams, p);
+ newClass.type = namePlusTypeParamsToTypeReference(job.parentType, job.builderImplClassNameArr, false, job.typeParams, p);
MessageSend invokeFillMethod = new MessageSend();
invokeFillMethod.receiver = newClass;
invokeFillMethod.selector = FILL_VALUES_METHOD_NAME;
invokeFillMethod.arguments = new Expression[] {new ThisReference(0, 0)};
out.statements = new Statement[] {new ReturnStatement(invokeFillMethod, pS, pE)};
+ if (job.checkerFramework.generateSideEffectFree()) {
+ out.annotations = new Annotation[] {generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)};
+ }
- if (cfv.generateUnique()) out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__UNIQUE)};
-
- createRelevantNonNullAnnotation(type, out);
- out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
+ createRelevantNonNullAnnotation(job.parentType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope);
return out;
}
@@ -650,17 +696,17 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* <pre>
* protected B $fillValuesFrom(final C instance) {
* super.$fillValuesFrom(instance);
- * Foobar.FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this);
+ * Foobar.FoobarBuilder.$fillValuesFromInstanceIntoBuilder(instance, this);
* return self();
* }
* </pre>
*/
- private MethodDeclaration generateFillValuesMethod(EclipseNode tdParent, boolean inherited, String builderGenericName, String classGenericName, String builderClassName, TypeParameter[] typeParams) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ private MethodDeclaration generateFillValuesMethod(SuperBuilderJob job, boolean inherited, String builderGenericName, String classGenericName) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = FILL_VALUES_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccProtected;
- if (inherited) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get())};
+ if (inherited) out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.parentType.get())};
out.returnType = new SingleTypeReference(builderGenericName.toCharArray(), 0);
TypeReference builderType = new SingleTypeReference(classGenericName.toCharArray(), 0);
@@ -679,7 +725,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
// Call the builder implemention's helper method that actually fills the values from the instance.
MessageSend callStaticFillValuesMethod = new MessageSend();
- callStaticFillValuesMethod.receiver = generateNameReference(tdParent, builderClassName.toCharArray(), 0);
+ callStaticFillValuesMethod.receiver = generateNameReference(job.parentType, job.builderAbstractClassNameArr, 0);
callStaticFillValuesMethod.selector = FILL_VALUES_STATIC_METHOD_NAME;
callStaticFillValuesMethod.arguments = new Expression[] {new SingleNameReference(INSTANCE_VARIABLE_NAME, 0), new ThisReference(0, 0)};
body.add(callStaticFillValuesMethod);
@@ -707,40 +753,40 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
* </pre>
* @param setterPrefix the prefix for setter methods
*/
- private MethodDeclaration generateStaticFillValuesMethod(EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, java.util.List<BuilderFieldData> builderFields, ASTNode source, String setterPrefix) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ private MethodDeclaration generateStaticFillValuesMethod(BuilderJob job, String setterPrefix) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = FILL_VALUES_STATIC_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic;
out.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
TypeReference[] wildcards = new TypeReference[] {new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND)};
- TypeReference builderType = generateParameterizedTypeReference(tdParent, builderClassName.toCharArray(), false, mergeToTypeReferences(typeParams, wildcards), 0);
+ TypeReference builderType = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), 0);
Argument builderArgument = new Argument(BUILDER_VARIABLE_NAME, 0, builderType, Modifier.FINAL);
TypeReference[] typerefs = null;
- if (typeParams.length > 0) {
- typerefs = new TypeReference[typeParams.length];
- for (int i = 0; i < typeParams.length; i++) typerefs[i] = new SingleTypeReference(typeParams[i].name, 0);
+ if (job.typeParams.length > 0) {
+ typerefs = new TypeReference[job.typeParams.length];
+ for (int i = 0; i < job.typeParams.length; i++) typerefs[i] = new SingleTypeReference(job.typeParams[i].name, 0);
}
- long p = source.sourceStart;
- p = (p << 32) | source.sourceEnd;
+ long p = job.getPos();
- TypeReference parentArgument = typerefs == null ? generateTypeReference(tdParent, p) : generateParameterizedTypeReference(tdParent, typerefs, p);
+ TypeReference parentArgument = typerefs == null ? generateTypeReference(job.parentType, p) : generateParameterizedTypeReference(job.parentType, typerefs, p);
out.arguments = new Argument[] {new Argument(INSTANCE_VARIABLE_NAME, 0, parentArgument, Modifier.FINAL), builderArgument};
// Add type params if there are any.
- if (typeParams.length > 0) out.typeParameters = copyTypeParams(typeParams, source);
+ if (job.typeParams.length > 0) out.typeParameters = copyTypeParams(job.typeParams, job.source);
List<Statement> body = new ArrayList<Statement>();
// Call the builder's setter methods to fill the values from the instance.
- for (BuilderFieldData bfd : builderFields) {
- MessageSend exec = createSetterCallWithInstanceValue(bfd, tdParent, source, setterPrefix);
+ for (BuilderFieldData bfd : job.builderFields) {
+ MessageSend exec = createSetterCallWithInstanceValue(bfd, job.parentType, job.source, setterPrefix);
body.add(exec);
}
out.statements = body.isEmpty() ? null : body.toArray(new Statement[0]);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
@@ -772,9 +818,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
ms.arguments = tgt;
} else {
Expression ifNull = new EqualExpression(tgt[0], new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
- MessageSend emptyCollection = new MessageSend();
- emptyCollection.receiver = generateQualifiedNameRef(source, bfd.singularData.getSingularizer().getEmptyMakerReceiver(bfd.singularData.getTargetFqn()));
- emptyCollection.selector = bfd.singularData.getSingularizer().getEmptyMakerSelector(bfd.singularData.getTargetFqn());
+ MessageSend emptyCollection = bfd.singularData.getSingularizer().getEmptyExpression(bfd.singularData.getTargetFqn(), bfd.singularData, type, source);
ms.arguments = new Expression[] {new ConditionalExpression(ifNull, emptyCollection, tgt[1])};
}
ms.receiver = new SingleNameReference(BUILDER_VARIABLE_NAME, 0);
@@ -782,14 +826,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
return ms;
}
- private MethodDeclaration generateAbstractSelfMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean override, String builderGenericName) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult);
+ private MethodDeclaration generateAbstractSelfMethod(BuilderJob job, boolean override, String builderGenericName) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = SELF_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccAbstract | ClassFileConstants.AccProtected | ExtraCompilerModifiers.AccSemicolonBody;
- Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get()) : null;
- Annotation rrAnn = cfv.generateReturnsReceiver() ? generateNamedAnnotation(tdParent.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER): null;
- Annotation sefAnn = cfv.generatePure() ? generateNamedAnnotation(tdParent.get(), CheckerFrameworkVersion.NAME__PURE): null;
+ Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.parentType.get()) : null;
+ Annotation rrAnn = job.checkerFramework.generateReturnsReceiver() ? generateNamedAnnotation(job.parentType.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER): null;
+ Annotation sefAnn = job.checkerFramework.generatePure() ? generateNamedAnnotation(job.parentType.get(), CheckerFrameworkVersion.NAME__PURE): null;
if (overrideAnn != null && rrAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn, sefAnn};
else if (overrideAnn != null && rrAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn};
else if (overrideAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
@@ -801,54 +845,52 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
return out;
}
- private MethodDeclaration generateSelfMethod(CheckerFrameworkVersion cfv, EclipseNode builderImplType, TypeParameter[] typeParams, long p) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderImplType.top().get()).compilationResult);
+ private MethodDeclaration generateSelfMethod(BuilderJob job) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = SELF_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccProtected;
- Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, builderImplType.get());
- Annotation rrAnn = cfv.generateReturnsReceiver() ? generateNamedAnnotation(builderImplType.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER) : null;
- Annotation sefAnn = cfv.generatePure() ? generateNamedAnnotation(builderImplType.get(), CheckerFrameworkVersion.NAME__PURE) : null;
+ Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.builderType.get());
+ Annotation rrAnn = job.checkerFramework.generateReturnsReceiver() ? generateNamedAnnotation(job.builderType.get(), CheckerFrameworkVersion.NAME__RETURNS_RECEIVER) : null;
+ Annotation sefAnn = job.checkerFramework.generatePure() ? generateNamedAnnotation(job.builderType.get(), CheckerFrameworkVersion.NAME__PURE) : null;
if (rrAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn, sefAnn};
else if (rrAnn != null) out.annotations = new Annotation[] {overrideAnn, rrAnn};
else if (sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
else out.annotations = new Annotation[] {overrideAnn};
- out.returnType = namePlusTypeParamsToTypeReference(builderImplType, typeParams, p);
+ out.returnType = namePlusTypeParamsToTypeReference(job.builderType, job.typeParams, job.getPos());
out.statements = new Statement[] {new ReturnStatement(new ThisReference(0, 0), 0, 0)};
return out;
}
- private MethodDeclaration generateAbstractBuildMethod(CheckerFrameworkVersion cfv, EclipseNode builderType, String methodName, List<BuilderFieldData> builderFields, boolean override,
- String classGenericName, ASTNode source) {
-
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ private MethodDeclaration generateAbstractBuildMethod(BuilderJob job, boolean override, String classGenericName) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody;
- out.selector = methodName.toCharArray();
+ out.selector = job.buildMethodName.toCharArray();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = new SingleTypeReference(classGenericName.toCharArray(), 0);
- Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source) : null;
- Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ Annotation overrideAnn = override ? makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.source) : null;
+ Annotation sefAnn = job.checkerFramework.generateSideEffectFree() ? generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
if (overrideAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
else if (overrideAnn != null) out.annotations = new Annotation[] {overrideAnn};
else if (sefAnn != null) out.annotations = new Annotation[] {sefAnn};
- out.receiver = HandleBuilder.generateBuildReceiver(cfv, builderType, builderFields, source);
- out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.receiver = HandleBuilder.generateBuildReceiver(job);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
- private MethodDeclaration generateBuildMethod(CheckerFrameworkVersion cfv, EclipseNode builderType, String name, TypeReference returnType, List<BuilderFieldData> builderFields, ASTNode source) {
- MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ private MethodDeclaration generateBuildMethod(BuilderJob job, TypeReference returnType) {
+ MethodDeclaration out = job.createNewMethodDeclaration();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
out.modifiers = ClassFileConstants.AccPublic;
- out.selector = name.toCharArray();
+ out.selector = job.buildMethodName.toCharArray();
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = returnType;
- Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source);
- Annotation sefAnn = cfv.generateSideEffectFree() ? generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
+ Annotation overrideAnn = makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.source);
+ Annotation sefAnn = job.checkerFramework.generateSideEffectFree() ? generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE): null;
if (sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn};
else out.annotations = new Annotation[] {overrideAnn};
@@ -858,43 +900,44 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
allocationStatement.arguments = new Expression[] {new ThisReference(0, 0)};
statements.add(new ReturnStatement(allocationStatement, 0, 0));
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
- out.receiver = HandleBuilder.generateBuildReceiver(cfv, builderType, builderFields, source);
- createRelevantNonNullAnnotation(builderType, out);
- out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ out.receiver = HandleBuilder.generateBuildReceiver(job);
+ createRelevantNonNullAnnotation(job.builderType, out);
+ out.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return out;
}
- private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) {
+ private MethodDeclaration generateCleanMethod(BuilderJob job) {
List<Statement> statements = new ArrayList<Statement>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, builderType, statements);
+ bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, job.builderType, statements);
}
}
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
thisUnclean.receiver = new ThisReference(0, 0);
statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
- MethodDeclaration decl = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ MethodDeclaration decl = job.createNewMethodDeclaration();
+ //new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
decl.selector = CLEAN_METHOD_NAME;
decl.modifiers = ClassFileConstants.AccPrivate;
decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
decl.statements = statements.toArray(new Statement[0]);
- decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ decl.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return decl;
}
- private void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) {
+ private void generateBuilderFields(BuilderJob job) {
List<EclipseNode> existing = new ArrayList<EclipseNode>();
- for (EclipseNode child : builderType.down()) {
+ for (EclipseNode child : job.builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
+ bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, job.builderType));
} else {
EclipseNode field = null, setFlag = null;
for (EclipseNode exists : existing) {
@@ -908,23 +951,23 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = copyType(bfd.type);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- field = injectFieldAndMarkGenerated(builderType, fd);
+ fd.traverse(new SetGeneratedByVisitor(job.source), (MethodScope) null);
+ field = injectFieldAndMarkGenerated(job.builderType, fd);
}
if (setFlag == null && bfd.nameOfSetFlag != null) {
FieldDeclaration fd = new FieldDeclaration(bfd.nameOfSetFlag, 0, 0);
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- injectFieldAndMarkGenerated(builderType, fd);
+ fd.traverse(new SetGeneratedByVisitor(job.source), (MethodScope) null);
+ injectFieldAndMarkGenerated(job.builderType, fd);
}
bfd.createdFields.add(field);
}
}
}
- private void generateSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, final String builderGenericName, String setterPrefix) {
+ private void generateSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, final String builderGenericName, String setterPrefix) {
boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() {
@@ -943,15 +986,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
};
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- generateSimpleSetterMethodForBuilder(cfv, builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode, bfd.annotations, bfd.originalFieldNode, setterPrefix);
+ generateSimpleSetterMethodForBuilder(job, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), bfd.annotations, bfd.originalFieldNode, setterPrefix);
} else {
- bfd.singularData.getSingularizer().generateMethods(cfv, bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
+ bfd.singularData.getSingularizer().generateMethods(job.checkerFramework, bfd.singularData, deprecate, job.builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
}
}
-
- private void generateSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, TypeReference returnType, Statement returnStatement, EclipseNode sourceNode, Annotation[] annosOnParam, EclipseNode originalFieldNode, String setterPrefix) {
- TypeDeclaration td = (TypeDeclaration) builderType.get();
- ASTNode source = sourceNode.get();
+
+ private void generateSimpleSetterMethodForBuilder(BuilderJob job, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, TypeReference returnType, Statement returnStatement, Annotation[] annosOnParam, EclipseNode originalFieldNode, String setterPrefix) {
+ TypeDeclaration td = (TypeDeclaration) job.builderType.get();
AbstractMethodDeclaration[] existing = td.methods;
if (existing == null) existing = EMPTY_METHODS;
int len = existing.length;
@@ -965,23 +1007,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
List<Annotation> methodAnnsList = Arrays.asList(EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode));
- if (cfv.generateReturnsReceiver()) {
+ if (job.checkerFramework.generateReturnsReceiver()) {
methodAnnsList = new ArrayList<Annotation>(methodAnnsList);
- methodAnnsList.add(generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER));
+ methodAnnsList.add(generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER));
}
MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, returnType, returnStatement, ClassFileConstants.AccPublic,
- sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(source, annosOnParam)) : Collections.<Annotation>emptyList());
- if (cfv.generateCalledMethods()) {
- char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED);
- SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart);
- ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0);
-
- QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(builderType, 0);
- typeReference.annotations = new Annotation[typeReference.tokens.length][];
- typeReference.annotations[0] = new Annotation[] {ann};
- setter.receiver = new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL);
- }
- injectMethod(builderType, setter);
+ job.sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(job.source, annosOnParam)) : Collections.<Annotation>emptyList());
+ if (job.checkerFramework.generateCalledMethods()) setter.receiver = generateNotCalledReceiver(job, setterName);
+ injectMethod(job.builderType, setter);
}
private void addObtainVia(BuilderFieldData bfd, EclipseNode node) {
@@ -1069,6 +1102,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
// 3. Add used type names.
if (td.fields != null) {
for (FieldDeclaration field : td.fields) {
+ if (field instanceof Initializer) continue;
char[][] typeName = field.type.getTypeName();
if (typeName.length >= 1) // Add the first token, because only that can collide.
usedNames.add(String.valueOf(typeName[0]));
@@ -1171,7 +1205,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
if (!def.isConstructor()) continue;
if (isTolerate(type, def)) continue;
- if (def.arguments.length != 1) continue;
+ if (def.arguments == null || def.arguments.length != 1) continue;
// Cannot use typeMatches() here, because the parameter could be fully-qualified, partially-qualified, or not qualified.
// A string-compare of the last part should work. If it's a false-positive, users could still @Tolerate it.
diff --git a/src/core/lombok/eclipse/handlers/HandleSynchronized.java b/src/core/lombok/eclipse/handlers/HandleSynchronized.java
index 37d6755c..18d1e7b7 100644
--- a/src/core/lombok/eclipse/handlers/HandleSynchronized.java
+++ b/src/core/lombok/eclipse/handlers/HandleSynchronized.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
@@ -36,6 +36,7 @@ import lombok.eclipse.DeferUntilPostDiet;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
@@ -51,12 +52,11 @@ import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.Synchronized} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@DeferUntilPostDiet
@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it.
public class HandleSynchronized extends EclipseAnnotationHandler<Synchronized> {
@@ -153,7 +153,6 @@ public class HandleSynchronized extends EclipseAnnotationHandler<Synchronized> {
annotationNode.addError("@Synchronized is legal only on methods in classes and enums.");
return;
}
-
boolean[] isStatic = { method.isStatic() };
char[] lockName = createLockField(annotation, annotationNode, isStatic, true);
if (lockName == null) return;
diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java
index 9b58474c..72491277 100644
--- a/src/core/lombok/eclipse/handlers/HandleToString.java
+++ b/src/core/lombok/eclipse/handlers/HandleToString.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
@@ -51,7 +51,6 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
@@ -66,11 +65,12 @@ import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.spi.Provides;
/**
* Handles the {@code ToString} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleToString extends EclipseAnnotationHandler<ToString> {
public void handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.TO_STRING_FLAG_USAGE, "@ToString");
diff --git a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java
index 338aab0d..9a18b20b 100644
--- a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java
+++ b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -25,8 +25,6 @@ import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import java.util.Arrays;
-
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
@@ -45,7 +43,6 @@ import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-import org.mangosdk.spi.ProviderFor;
import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
@@ -54,12 +51,13 @@ import lombok.core.AST.Kind;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.UtilityClass;
+import lombok.spi.Provides;
/**
* Handles the {@code lombok.experimental.UtilityClass} annotation for eclipse.
*/
+@Provides
@HandlerPriority(-4096) //-2^12; to ensure @FieldDefaults picks up on the 'static' we set here.
-@ProviderFor(EclipseAnnotationHandler.class)
public class HandleUtilityClass extends EclipseAnnotationHandler<UtilityClass> {
@Override public void handle(AnnotationValues<UtilityClass> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.UTILITY_CLASS_FLAG_USAGE, "@UtilityClass");
@@ -71,7 +69,7 @@ public class HandleUtilityClass extends EclipseAnnotationHandler<UtilityClass> {
private static boolean checkLegality(EclipseNode typeNode, EclipseNode errorNode) {
if (!isClass(typeNode)) {
- errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, annotation, or record).");
+ errorNode.addError("@UtilityClass is only supported on a class.");
return false;
}
@@ -153,37 +151,28 @@ public class HandleUtilityClass extends EclipseAnnotationHandler<UtilityClass> {
ASTNode source = sourceNode.get();
TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
- long p = (long) source.sourceStart << 32 | source.sourceEnd;
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
constructor.modifiers = ClassFileConstants.AccPrivate;
constructor.selector = typeDeclaration.name;
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
- constructor.constructorCall.sourceStart = source.sourceStart;
- constructor.constructorCall.sourceEnd = source.sourceEnd;
constructor.thrownExceptions = null;
constructor.typeParameters = null;
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
- constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
constructor.arguments = null;
- AllocationExpression exception = new AllocationExpression();
- setGeneratedBy(exception, source);
long[] ps = new long[JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION.length];
- Arrays.fill(ps, p);
+ AllocationExpression exception = new AllocationExpression();
exception.type = new QualifiedTypeReference(JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION, ps);
- setGeneratedBy(exception.type, source);
exception.arguments = new Expression[] {
- new StringLiteral(UNSUPPORTED_MESSAGE, source.sourceStart, source.sourceEnd, 0)
+ new StringLiteral(UNSUPPORTED_MESSAGE, 0, 0, 0)
};
- setGeneratedBy(exception.arguments[0], source);
- ThrowStatement throwStatement = new ThrowStatement(exception, source.sourceStart, source.sourceEnd);
- setGeneratedBy(throwStatement, source);
+ ThrowStatement throwStatement = new ThrowStatement(exception, 0, 0);
constructor.statements = new Statement[] {throwStatement};
+ constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
injectMethod(typeNode, constructor);
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java
index 3742ac00..ac53e27e 100644
--- a/src/core/lombok/eclipse/handlers/HandleVal.java
+++ b/src/core/lombok/eclipse/handlers/HandleVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2018 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -31,6 +31,7 @@ import lombok.eclipse.DeferUntilPostDiet;
import lombok.eclipse.EclipseASTAdapter;
import lombok.eclipse.EclipseASTVisitor;
import lombok.eclipse.EclipseNode;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
@@ -39,12 +40,11 @@ import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.mangosdk.spi.ProviderFor;
/*
* This class just handles 3 basic error cases. The real meat of eclipse 'val' support is in {@code PatchVal} and {@code PatchValEclipse}.
*/
-@ProviderFor(EclipseASTVisitor.class)
+@Provides(EclipseASTVisitor.class)
@DeferUntilPostDiet
@HandlerPriority(65536) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated.
public class HandleVal extends EclipseASTAdapter {
diff --git a/src/core/lombok/eclipse/handlers/HandleValue.java b/src/core/lombok/eclipse/handlers/HandleValue.java
index abea5603..7a73e5ed 100644
--- a/src/core/lombok/eclipse/handlers/HandleValue.java
+++ b/src/core/lombok/eclipse/handlers/HandleValue.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
@@ -34,17 +34,17 @@ import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists;
import lombok.experimental.NonFinal;
+import lombok.spi.Provides;
import lombok.Value;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.Value} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
@HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier.
public class HandleValue extends EclipseAnnotationHandler<Value> {
private HandleFieldDefaults handleFieldDefaults = new HandleFieldDefaults();
@@ -59,13 +59,11 @@ public class HandleValue extends EclipseAnnotationHandler<Value> {
Value ann = annotation.getInstance();
EclipseNode typeNode = annotationNode.up();
- TypeDeclaration typeDecl = null;
- if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
-
if (!isClass(typeNode)) {
annotationNode.addError("@Value is only supported on a class.");
return;
}
+ TypeDeclaration typeDecl = (TypeDeclaration) typeNode.get();
// Make class final.
if (!hasAnnotation(NonFinal.class, typeNode)) {
diff --git a/src/core/lombok/eclipse/handlers/HandleWith.java b/src/core/lombok/eclipse/handlers/HandleWith.java
index 83357710..bfad682b 100644
--- a/src/core/lombok/eclipse/handlers/HandleWith.java
+++ b/src/core/lombok/eclipse/handlers/HandleWith.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2020 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
@@ -38,6 +38,7 @@ import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
@@ -57,9 +58,8 @@ 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.lookup.ExtraCompilerModifiers;
-import org.mangosdk.spi.ProviderFor;
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleWith extends EclipseAnnotationHandler<With> {
public boolean generateWithForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelWith) {
if (checkForTypeLevelWith) {
@@ -290,6 +290,7 @@ public class HandleWith extends EclipseAnnotationHandler<With> {
EclipseHandlerUtil.createRelevantNonNullAnnotation(fieldNode, method);
method.traverse(new SetGeneratedByVisitor(source), parent.scope);
+ copyJavadoc(fieldNode, method, CopyJavadoc.WITH);
return method;
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleWithBy.java b/src/core/lombok/eclipse/handlers/HandleWithBy.java
index 5f229aaf..a8d13a84 100644
--- a/src/core/lombok/eclipse/handlers/HandleWithBy.java
+++ b/src/core/lombok/eclipse/handlers/HandleWithBy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Project Lombok Authors.
+ * Copyright (C) 2020-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -51,7 +51,6 @@ import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
-import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
@@ -63,8 +62,9 @@ import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.WithBy;
+import lombok.spi.Provides;
-@ProviderFor(EclipseAnnotationHandler.class)
+@Provides
public class HandleWithBy extends EclipseAnnotationHandler<WithBy> {
public boolean generateWithByForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelWithBy) {
if (checkForTypeLevelWithBy) {
@@ -373,6 +373,7 @@ public class HandleWithBy extends EclipseAnnotationHandler<WithBy> {
createRelevantNonNullAnnotation(fieldNode, method);
method.traverse(new SetGeneratedByVisitor(source), parent.scope);
+ copyJavadoc(fieldNode, method, CopyJavadoc.WITH_BY);
return method;
}
}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java
index 5956c01b..088a4506 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,12 +21,11 @@
*/
package lombok.eclipse.handlers.singulars;
-import org.mangosdk.spi.ProviderFor;
-
import lombok.core.LombokImmutableList;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.spi.Provides;
-@ProviderFor(EclipseSingularizer.class)
+@Provides(EclipseSingularizer.class)
public class EclipseGuavaMapSingularizer extends EclipseGuavaSingularizer {
// TODO cgcc.ImmutableMultimap, cgcc.ImmutableListMultimap, cgcc.ImmutableSetMultimap
// TODO cgcc.ImmutableClassToInstanceMap
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java
index 326a9179..1f3603da 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,12 +21,11 @@
*/
package lombok.eclipse.handlers.singulars;
-import org.mangosdk.spi.ProviderFor;
-
import lombok.core.LombokImmutableList;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.spi.Provides;
-@ProviderFor(EclipseSingularizer.class)
+@Provides(EclipseSingularizer.class)
public class EclipseGuavaSetListSingularizer extends EclipseGuavaSingularizer {
// TODO com.google.common.collect.ImmutableRangeSet
// TODO com.google.common.collect.ImmutableMultiset and com.google.common.collect.ImmutableSortedMultiset
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
index 395d2e59..7dcf18c9 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -279,7 +279,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
protected abstract String getAddMethodName();
protected abstract String getAddAllTypeName();
- protected int getTypeArgumentsCount() {
+ @Override protected int getTypeArgumentsCount() {
return getArgumentSuffixes().size();
}
}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java
index 4d25811b..ee92ad5a 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,12 +21,11 @@
*/
package lombok.eclipse.handlers.singulars;
-import org.mangosdk.spi.ProviderFor;
-
import lombok.core.LombokImmutableList;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.spi.Provides;
-@ProviderFor(EclipseSingularizer.class)
+@Provides(EclipseSingularizer.class)
public class EclipseGuavaTableSingularizer extends EclipseGuavaSingularizer {
private static final LombokImmutableList<String> SUFFIXES =
LombokImmutableList.of("rowKey", "columnKey", "value");
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
index deab4530..882b7adc 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -156,7 +156,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up()));
md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
-
+
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
data.setGeneratedByRecursive(md);
HandleNonNull.INSTANCE.fix(injectMethod(builderType, md));
@@ -194,9 +194,13 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up()));
md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
-
+
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
+
+ @Override protected int getTypeArgumentsCount() {
+ return 1;
+ }
}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java
index bf50aef6..0d0f3130 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2019 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -31,6 +31,7 @@ import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
@@ -45,10 +46,8 @@ import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.mangosdk.spi.ProviderFor;
-
-@ProviderFor(EclipseSingularizer.class)
+@Provides(EclipseSingularizer.class)
public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.List", "java.util.Collection", "java.lang.Iterable");
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
index 1a40369d..a766612f 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -50,7 +50,6 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.core.LombokImmutableList;
@@ -62,8 +61,9 @@ import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
import lombok.eclipse.handlers.EclipseSingularsRecipes.StatementMaker;
import lombok.eclipse.handlers.EclipseSingularsRecipes.TypeReferenceMaker;
import lombok.eclipse.handlers.HandleNonNull;
+import lombok.spi.Provides;
-@ProviderFor(EclipseSingularizer.class)
+@Provides(EclipseSingularizer.class)
public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
@@ -349,4 +349,8 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, true, true, false, true, "TreeMap", builderVariable));
}
}
+
+ @Override protected int getTypeArgumentsCount() {
+ return 2;
+ }
}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java
index 2076ec7d..a432f3fe 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2019 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -27,11 +27,11 @@ import lombok.core.LombokImmutableList;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+import lombok.spi.Provides;
import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.mangosdk.spi.ProviderFor;
-@ProviderFor(EclipseSingularizer.class)
+@Provides(EclipseSingularizer.class)
public class EclipseJavaUtilSetSingularizer extends EclipseJavaUtilListSetSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.Set", "java.util.SortedSet", "java.util.NavigableSet");
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/HandlerLibrary.java b/src/core/lombok/javac/HandlerLibrary.java
index 9e7b8fe5..c2bf8512 100644
--- a/src/core/lombok/javac/HandlerLibrary.java
+++ b/src/core/lombok/javac/HandlerLibrary.java
@@ -65,7 +65,7 @@ public class HandlerLibrary {
/**
* Creates a new HandlerLibrary that will report any problems or errors to the provided messager.
- * You probably want to use {@link #load(Messager)} instead.
+ * You probably want to use {@link #load(Messager, Trees)} instead.
*/
public HandlerLibrary(Messager messager) {
ConfigurationKeysLoader.LoaderLoader.loadAllConfigurationKeys();
diff --git a/src/core/lombok/javac/Javac6BasedLombokOptions.java b/src/core/lombok/javac/Javac6BasedLombokOptions.java
index fc73181c..93f448a7 100644
--- a/src/core/lombok/javac/Javac6BasedLombokOptions.java
+++ b/src/core/lombok/javac/Javac6BasedLombokOptions.java
@@ -58,7 +58,7 @@ public class Javac6BasedLombokOptions extends LombokOptions {
@Override public void putJavacOption(String optionName, String value) {
try {
- options_put.invoke(this, optionName_valueOf.invoke(null, optionName), value);
+ Permit.invoke(options_put, this, Permit.invoke(optionName_valueOf, null, optionName), value);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Can't initialize Javac6-based lombok options due to reflection issue.", e);
} catch (InvocationTargetException e) {
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index 86ff7646..f58de60f 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.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
@@ -21,6 +21,7 @@
*/
package lombok.javac;
+import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;
@@ -110,14 +111,97 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
return memoizedAbsoluteFileLocation;
}
+ private static Class<?> wrappedFileObjectClass, sbtJavaFileObjectClass, sbtMappedVirtualFileClass, sbtOptionClass;
+ private static Field wrappedFileObjectField, sbtJavaFileObjectField, sbtMappedVirtualFilePathField, sbtMappedVirtualFileRootsField, sbtOptionField;
+ private static Method sbtMapGetMethod;
+
public static URI getAbsoluteFileLocation(JCCompilationUnit cu) {
try {
- return cu.sourcefile.toUri();
+ URI uri = cu.sourcefile.toUri();
+ String fn = uri.toString();
+ if (fn.startsWith("file:")) return uri;
+ URI sbtUri = tryGetSbtFile(cu.sourcefile);
+ if (sbtUri != null) return sbtUri;
+ return uri;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private static URI tryGetSbtFile(JavaFileObject sourcefile) {
+ try {
+ return tryGetSbtFile_(sourcefile);
} catch (Exception e) {
return null;
}
}
+ private static URI tryGetSbtFile_(JavaFileObject sourcefile) throws Exception {
+ Class<?> c = sourcefile.getClass();
+ String cn;
+
+ if (wrappedFileObjectClass == null) {
+ if (!c.getName().equals("com.sun.tools.javac.api.ClientCodeWrapper$WrappedJavaFileObject")) return null;
+ wrappedFileObjectClass = c;
+ }
+ if (c != wrappedFileObjectClass) return null;
+
+ if (wrappedFileObjectField == null) wrappedFileObjectField = Permit.permissiveGetField(wrappedFileObjectClass.getSuperclass(), "clientFileObject");
+ if (wrappedFileObjectField == null) return null;
+ Object fileObject = wrappedFileObjectField.get(sourcefile);
+ c = fileObject.getClass();
+
+ if (sbtJavaFileObjectClass == null) {
+ cn = c.getName();
+ if (!cn.startsWith("sbt.") || !cn.endsWith("JavaFileObject")) return null;
+ sbtJavaFileObjectClass = c;
+ }
+ if (sbtJavaFileObjectClass != c) return null;
+ if (sbtJavaFileObjectField == null) sbtJavaFileObjectField = Permit.permissiveGetField(sbtJavaFileObjectClass, "underlying");
+ if (sbtJavaFileObjectField == null) return null;
+
+ Object mappedVirtualFile = sbtJavaFileObjectField.get(fileObject);
+ c = mappedVirtualFile.getClass();
+
+ if (sbtMappedVirtualFileClass == null) {
+ cn = c.getName();
+ if (!cn.startsWith("sbt.") || !cn.endsWith("MappedVirtualFile")) return null;
+ sbtMappedVirtualFileClass = c;
+ }
+ if (sbtMappedVirtualFilePathField == null) sbtMappedVirtualFilePathField = Permit.permissiveGetField(sbtMappedVirtualFileClass, "encodedPath");
+ if (sbtMappedVirtualFilePathField == null) return null;
+ if (sbtMappedVirtualFileRootsField == null) sbtMappedVirtualFileRootsField = Permit.permissiveGetField(sbtMappedVirtualFileClass, "rootPathsMap");
+ if (sbtMappedVirtualFileRootsField == null) return null;
+
+ String encodedPath = (String) sbtMappedVirtualFilePathField.get(mappedVirtualFile);
+ if (!encodedPath.startsWith("${")) {
+ File maybeAbsoluteFile = new File(encodedPath);
+ if (maybeAbsoluteFile.exists()) {
+ return maybeAbsoluteFile.toURI();
+ } else {
+ return null;
+ }
+ }
+ int idx = encodedPath.indexOf('}');
+ if (idx == -1) return null;
+ String base = encodedPath.substring(2, idx);
+ Object roots = sbtMappedVirtualFileRootsField.get(mappedVirtualFile);
+ if (sbtMapGetMethod == null) sbtMapGetMethod = Permit.getMethod(roots.getClass(), "get", Object.class);
+ if (sbtMapGetMethod == null) return null;
+
+ Object option = sbtMapGetMethod.invoke(roots, base);
+ c = option.getClass();
+ if (sbtOptionClass == null) {
+ if (c.getName().equals("scala.Some")) sbtOptionClass = c;
+ }
+ if (c != sbtOptionClass) return null;
+ if (sbtOptionField == null) sbtOptionField = Permit.permissiveGetField(sbtOptionClass, "value");
+ if (sbtOptionField == null) return null;
+
+ Object path = sbtOptionField.get(option);
+ return new File(path.toString() + encodedPath.substring(idx + 1)).toURI();
+ }
+
private static String sourceName(JCCompilationUnit cu) {
return cu.sourcefile == null ? null : cu.sourcefile.toString();
}
@@ -397,11 +481,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
}
private JCTree getBody(JCTree jcTree) {
- try {
- return (JCTree) getBodyMethod(jcTree.getClass()).invoke(jcTree);
- } catch (Exception e) {
- throw Javac.sneakyThrow(e);
- }
+ return (JCTree) Permit.invokeSneaky(getBodyMethod(jcTree.getClass()), jcTree);
}
private final static ConcurrentMap<Class<?>, Method> getBodyMethods = new ConcurrentHashMap<Class<?>, Method>();
@@ -662,42 +742,26 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
}
@Override void error1(DiagnosticPosition pos, String message) {
- try {
- Object error = this.errorKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
- errorMethod.invoke(log, multiple, pos, error);
- } catch (Throwable t) {
- //t.printStackTrace();
- }
+ Object error = Permit.invokeSneaky(this.errorKey, diags, PROC_MESSAGER, new Object[] { message });
+ if (error != null) Permit.invokeSneaky(errorMethod, log, multiple, pos, error);
}
@Override
void warning1(DiagnosticPosition pos, String message) {
- try {
- Object warning = this.warningKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
- warningMethod.invoke(log, pos, warning);
- } catch (Throwable t) {
- //t.printStackTrace();
- }
+ Object warning = Permit.invokeSneaky(this.warningKey, diags, PROC_MESSAGER, new Object[] { message });
+ if (warning != null) Permit.invokeSneaky(warningMethod, log, pos, warning);
}
@Override
void mandatoryWarning1(DiagnosticPosition pos, String message) {
- try {
- Object warning = this.warningKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
- mandatoryWarningMethod.invoke(log, pos, warning);
- } catch (Throwable t) {
- //t.printStackTrace();
- }
+ Object warning = Permit.invokeSneaky(this.warningKey, diags, PROC_MESSAGER, new Object[] { message });
+ if (warning != null) Permit.invokeSneaky(mandatoryWarningMethod, log, pos, warning);
}
@Override
void note(DiagnosticPosition pos, String message) {
- try {
- Object note = this.noteKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
- noteMethod.invoke(log, pos, note);
- } catch (Throwable t) {
- //t.printStackTrace();
- }
+ Object note = Permit.invokeSneaky(this.noteKey, diags, PROC_MESSAGER, new Object[] { message });
+ if (note != null) Permit.invokeSneaky(noteMethod, log, pos, note);
}
}
}
diff --git a/src/core/lombok/javac/JavacASTVisitor.java b/src/core/lombok/javac/JavacASTVisitor.java
index 9b67dda3..e8fd295c 100644
--- a/src/core/lombok/javac/JavacASTVisitor.java
+++ b/src/core/lombok/javac/JavacASTVisitor.java
@@ -22,6 +22,7 @@
package lombok.javac;
import java.io.PrintStream;
+import java.lang.reflect.Field;
import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Flags;
@@ -32,6 +33,7 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.util.List;
/**
* Implement so you can ask any JavacAST.LombokNode to traverse depth-first through all children,
@@ -223,6 +225,26 @@ public interface JavacASTVisitor {
} else type = "METHOD";
print("<%s %s> %s returns: %s", type, method.name, printFlags(method.mods.flags), method.restype);
indent++;
+ JCVariableDecl recv;
+ try {
+ Field f = JCMethodDecl.class.getField("recvparam");
+ recv = (JCVariableDecl) f.get(method);
+ } catch (Exception ignore) {
+ recv = null;
+ }
+
+ if (recv != null) {
+ List<JCAnnotation> annotations = recv.mods.annotations;
+ if (recv.mods != null) annotations = recv.mods.annotations;
+ boolean innerContent = annotations != null && annotations.isEmpty();
+ print("<RECEIVER-PARAM (%s) %s %s%s> %s", recv.vartype == null ? "null" : recv.vartype.getClass().toString(), recv.vartype, recv.name, innerContent ? "" : " /", printFlags(recv.mods.flags));
+ if (innerContent) {
+ indent++;
+ for (JCAnnotation ann : annotations) print("<ANNOTATION: %s />", ann);
+ indent--;
+ print("</RECEIVER-PARAM>");
+ }
+ }
if (printContent) {
if (method.body == null) print("(ABSTRACT)");
else print("%s", method.body);
@@ -237,11 +259,11 @@ public interface JavacASTVisitor {
@Override public void endVisitMethod(JavacNode node, JCMethodDecl method) {
if (printContent) disablePrinting--;
indent--;
- print("</%s %s>", "XMETHOD", method.name);
+ print("</%s %s>", "METHOD", method.name);
}
@Override public void visitMethodArgument(JavacNode node, JCVariableDecl arg, JCMethodDecl method) {
- print("<METHODARG %s %s> %s", arg.vartype, arg.name, printFlags(arg.mods.flags));
+ print("<METHODARG (%s) %s %s> %s", arg.vartype.getClass().toString(), arg.vartype, arg.name, printFlags(arg.mods.flags));
indent++;
}
diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java
index e648cd51..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
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java
index 6b2f4637..e96079e0 100644
--- a/src/core/lombok/javac/JavacResolution.java
+++ b/src/core/lombok/javac/JavacResolution.java
@@ -25,7 +25,6 @@ import static lombok.javac.Javac.*;
import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.Collection;
@@ -65,7 +64,6 @@ import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
-import lombok.Lombok;
import lombok.core.debug.AssertionLogger;
import lombok.permit.Permit;
@@ -73,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);
@@ -251,27 +259,27 @@ public class JavacResolution {
private static class ReflectiveAccess {
private static Method UPPER_BOUND;
+ private static Throwable initError;
static {
Method upperBound = null;
try {
upperBound = Permit.getMethod(Types.class, "upperBound", Type.class);
- } catch (Throwable ignore) {}
+ } catch (Throwable e) {
+ initError = e;
+ }
+
if (upperBound == null) try {
upperBound = Permit.getMethod(Types.class, "wildUpperBound", Type.class);
- } catch (Throwable ignore) {}
+ } catch (Throwable e) {
+ initError = e;
+ }
UPPER_BOUND = upperBound;
}
public static Type Types_upperBound(Types types, Type type) {
- try {
- return (Type) UPPER_BOUND.invoke(types, type);
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e.getCause());
- } catch (Exception e) {
- throw Lombok.sneakyThrow(e);
- }
+ return (Type) Permit.invokeSneaky(initError, UPPER_BOUND, types, type);
}
}
@@ -354,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.
@@ -452,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 368928d4..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,9 +34,9 @@ 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;
final class InterceptingJavaFileObject implements LombokFileObject {
private final JavaFileObject delegate;
@@ -63,16 +62,8 @@ final class InterceptingJavaFileObject implements LombokFileObject {
}
@Override public CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
- if (decoderMethod == null) {
- throw new UnsupportedOperationException();
- }
- try {
- return (CharsetDecoder) decoderMethod.invoke(delegate, ignoreEncodingErrors);
- } catch (IllegalAccessException e) {
- throw Lombok.sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e);
- }
+ if (decoderMethod == null) throw new UnsupportedOperationException();
+ return (CharsetDecoder) Permit.invokeSneaky(decoderMethod, delegate, ignoreEncodingErrors);
}
@Override public boolean equals(Object obj) {
diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java
index 852e5de6..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
@@ -24,8 +24,10 @@ package lombok.javac.apt;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
@@ -61,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.
@@ -154,10 +158,10 @@ public class LombokProcessor extends AbstractProcessor {
disablePartialReparseInNetBeansEditor(context);
try {
Method keyMethod = Permit.getMethod(Context.class, "key", Class.class);
- Object key = keyMethod.invoke(context, JavaFileManager.class);
+ Object key = Permit.invoke(keyMethod, context, JavaFileManager.class);
Field htField = Permit.getField(Context.class, "ht");
@SuppressWarnings("unchecked")
- Map<Object,Object> ht = (Map<Object,Object>) htField.get(context);
+ Map<Object,Object> ht = (Map<Object,Object>) Permit.get(htField, context);
final JavaFileManager originalFiler = (JavaFileManager) ht.get(key);
if (!(originalFiler instanceof InterceptingJavaFileManager)) {
final Messager messager = processingEnv.getMessager();
@@ -180,10 +184,10 @@ public class LombokProcessor extends AbstractProcessor {
private void replaceFileManagerJdk9(Context context, JavaFileManager newFiler) {
try {
- JavaCompiler compiler = (JavaCompiler) Permit.getMethod(JavaCompiler.class, "instance", Context.class).invoke(null, context);
+ JavaCompiler compiler = (JavaCompiler) Permit.invoke(Permit.getMethod(JavaCompiler.class, "instance", Context.class), null, context);
try {
Field fileManagerField = Permit.getField(JavaCompiler.class, "fileManager");
- fileManagerField.set(compiler, newFiler);
+ Permit.set(fileManagerField, compiler, newFiler);
}
catch (Exception e) {}
@@ -191,7 +195,7 @@ public class LombokProcessor extends AbstractProcessor {
Field writerField = Permit.getField(JavaCompiler.class, "writer");
ClassWriter writer = (ClassWriter) writerField.get(compiler);
Field fileManagerField = Permit.getField(ClassWriter.class, "fileManager");
- fileManagerField.set(writer, newFiler);
+ Permit.set(fileManagerField, writer, newFiler);
}
catch (Exception e) {}
}
@@ -213,8 +217,8 @@ public class LombokProcessor extends AbstractProcessor {
private void disablePartialReparseInNetBeansEditor(Context context) {
try {
Class<?> cancelServiceClass = Class.forName("com.sun.tools.javac.util.CancelService");
- Method cancelServiceInstace = Permit.getMethod(cancelServiceClass, "instance", Context.class);
- Object cancelService = cancelServiceInstace.invoke(null, context);
+ Method cancelServiceInstance = Permit.getMethod(cancelServiceClass, "instance", Context.class);
+ Object cancelService = Permit.invoke(cancelServiceInstance, null, context);
if (cancelService == null) return;
Field parserField = Permit.getField(cancelService.getClass(), "parser");
Object parser = parserField.get(cancelService);
@@ -386,8 +390,8 @@ public class LombokProcessor extends AbstractProcessor {
try {
if (qualifiedNamableClass == null) qualifiedNamableClass = Class.forName("javax.lang.model.element.QualifiedNamable");
if (!qualifiedNamableClass.isInstance(element)) return null;
- if (qualifiedNamableQualifiedNameMethod == null) qualifiedNamableQualifiedNameMethod = qualifiedNamableClass.getMethod("getQualifiedName");
- String name = qualifiedNamableQualifiedNameMethod.invoke(element).toString().trim();
+ if (qualifiedNamableQualifiedNameMethod == null) qualifiedNamableQualifiedNameMethod = Permit.getMethod(qualifiedNamableClass, "getQualifiedName");
+ String name = Permit.invoke(qualifiedNamableQualifiedNameMethod, element).toString().trim();
return name.isEmpty() ? null : name;
} catch (ClassNotFoundException e) {
return null;
@@ -428,22 +432,108 @@ 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
for (Class<?> procEnvClass = procEnv.getClass(); procEnvClass != null; procEnvClass = procEnvClass.getSuperclass()) {
- try {
- return getJavacProcessingEnvironment(tryGetDelegateField(procEnvClass, procEnv));
- } catch (final Exception e) {
- // delegate field was not found, try on superclass
- }
+ Object delegate = tryGetDelegateField(procEnvClass, procEnv);
+ if (delegate == null) delegate = tryGetProxyDelegateToField(procEnvClass, procEnv);
+ if (delegate == null) delegate = tryGetProcessingEnvField(procEnvClass, procEnv);
+
+ if (delegate != null) return getJavacProcessingEnvironment(delegate);
+ // delegate field was not found, try on superclass
}
processingEnv.getMessager().printMessage(Kind.WARNING,
"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
@@ -454,11 +544,12 @@ public class LombokProcessor extends AbstractProcessor {
// try to find a "delegate" field in the object, and use this to check for a JavacFiler
for (Class<?> filerClass = filer.getClass(); filerClass != null; filerClass = filerClass.getSuperclass()) {
- try {
- return getJavacFiler(tryGetDelegateField(filerClass, filer));
- } catch (final Exception e) {
- // delegate field was not found, try on superclass
- }
+ Object delegate = tryGetDelegateField(filerClass, filer);
+ if (delegate == null) delegate = tryGetProxyDelegateToField(filerClass, filer);
+ if (delegate == null) delegate = tryGetFilerField(filerClass, filer);
+
+ if (delegate != null) return getJavacFiler(delegate);
+ // delegate field was not found, try on superclass
}
processingEnv.getMessager().printMessage(Kind.WARNING,
@@ -466,7 +557,48 @@ public class LombokProcessor extends AbstractProcessor {
return null;
}
- private Object tryGetDelegateField(Class<?> delegateClass, Object instance) throws Exception {
- return Permit.getField(delegateClass, "delegate").get(instance);
+ /**
+ * Gradle incremental processing
+ */
+ private Object tryGetDelegateField(Class<?> delegateClass, Object instance) {
+ try {
+ return Permit.getField(delegateClass, "delegate").get(instance);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Kotlin incremental processing
+ */
+ private Object tryGetProcessingEnvField(Class<?> delegateClass, Object instance) {
+ try {
+ return Permit.getField(delegateClass, "processingEnv").get(instance);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Kotlin incremental processing
+ */
+ private Object tryGetFilerField(Class<?> delegateClass, Object instance) {
+ try {
+ return Permit.getField(delegateClass, "filer").get(instance);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * IntelliJ IDEA >= 2020.3
+ */
+ private Object tryGetProxyDelegateToField(Class<?> delegateClass, Object instance) {
+ try {
+ InvocationHandler handler = Proxy.getInvocationHandler(instance);
+ return Permit.getField(handler.getClass(), "val$delegateTo").get(handler);
+ } catch (Exception e) {
+ return null;
+ }
}
}
diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java
index f15bf74c..e0de363d 100644
--- a/src/core/lombok/javac/apt/Processor.java
+++ b/src/core/lombok/javac/apt/Processor.java
@@ -222,7 +222,7 @@ public class Processor extends AbstractProcessor {
* We just return the latest version of whatever JDK we run on. Stupid? Yeah, but it's either that or warnings on all versions but 1.
*/
@Override public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.values()[SourceVersion.values().length - 1];
+ return SourceVersion.latest();
}
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
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 f9675813..a25baeb0 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
@@ -27,13 +27,9 @@ import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
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;
@@ -55,6 +51,7 @@ import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
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.Name;
@@ -82,18 +79,102 @@ 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();
+ static final String CLEAN_FIELD_NAME = "$lombokUnclean";
+ static final String CLEAN_METHOD_NAME = "$lombokClean";
+ static final String TO_BUILDER_METHOD_NAME = "toBuilder";
+ static final String DEFAULT_PREFIX = "$default$";
+ static final String SET_PREFIX = "$set";
+ static final String VALUE_PREFIX = "$value";
+ static final String BUILDER_TEMP_VAR = "builder";
+ static final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
+
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
if (expr instanceof JCLiteral) return ((Integer) ((JCLiteral) expr).value) != 0;
return ((Boolean) expr).booleanValue();
}
+ static class BuilderJob {
+ CheckerFrameworkVersion checkerFramework;
+ JavacNode parentType;
+ String builderMethodName, buildMethodName;
+ boolean isStatic;
+ List<JCTypeParameter> typeParams;
+ List<JCTypeParameter> builderTypeParams;
+ JavacNode sourceNode;
+ java.util.List<BuilderFieldData> builderFields;
+ AccessLevel accessInners, accessOuters;
+ boolean oldFluent, oldChain, toBuilder;
+
+ JavacNode builderType;
+ String builderClassName;
+
+ void init(AnnotationValues<Builder> annValues, Builder ann, JavacNode node) {
+ accessOuters = ann.access();
+ if (accessOuters == null) accessOuters = AccessLevel.PUBLIC;
+ if (accessOuters == AccessLevel.NONE) {
+ sourceNode.addError("AccessLevel.NONE is not valid here");
+ accessOuters = AccessLevel.PUBLIC;
+ }
+ accessInners = accessOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessOuters;
+
+ oldFluent = toBoolean(annValues.getActualExpression("fluent"), true);
+ oldChain = toBoolean(annValues.getActualExpression("chain"), true);
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ builderClassName = fixBuilderClassName(node, ann.builderClassName());
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ if (builderClassName == null) builderClassName = "";
+ }
+
+ static String fixBuilderClassName(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;
+ return "*Builder";
+ }
+
+ String replaceBuilderClassName(Name name) {
+ if (builderClassName.indexOf('*') == -1) return builderClassName;
+ return builderClassName.replace("*", name.toString());
+ }
+
+ JCExpression createBuilderParentTypeReference() {
+ return namePlusTypeParamsToTypeReference(parentType.getTreeMaker(), parentType, typeParams);
+ }
+
+ Name getBuilderClassName() {
+ return parentType.toName(builderClassName);
+ }
+
+ List<JCTypeParameter> copyTypeParams() {
+ return JavacHandlerUtil.copyTypeParams(sourceNode, typeParams);
+ }
+
+ Name toName(String name) {
+ return parentType.toName(name);
+ }
+
+ Context getContext() {
+ return parentType.getContext();
+ }
+
+ JavacTreeMaker getTreeMaker() {
+ return parentType.getTreeMaker();
+ }
+ }
+
static class BuilderFieldData {
List<JCAnnotation> annotations;
JCExpression type;
@@ -111,74 +192,56 @@ 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");
- CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
-
- Builder builderInstance = annotation.getInstance();
- AccessLevel accessForOuters = builderInstance.access();
- if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC;
- if (accessForOuters == AccessLevel.NONE) {
- annotationNode.addError("AccessLevel.NONE is not valid here");
- accessForOuters = AccessLevel.PUBLIC;
- }
- AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters;
-
- // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
- boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
- boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
-
- String builderMethodName = builderInstance.builderMethodName();
- String buildMethodName = builderInstance.buildMethodName();
- String builderClassName = builderInstance.builderClassName();
- String toBuilderMethodName = "toBuilder";
- boolean toBuilder = builderInstance.toBuilder();
- java.util.List<Name> typeArgsForToBuilder = null;
+ BuilderJob job = new BuilderJob();
+ job.sourceNode = annotationNode;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
- if (builderClassName == null) builderClassName = "";
+ Builder annInstance = annotation.getInstance();
+ job.init(annotation, annInstance, annotationNode);
+ java.util.List<Name> typeArgsForToBuilder = null;
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
- if (!builderClassName.isEmpty()) {
- if (!checkName("builderClassName", builderClassName, annotationNode)) return;
- }
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
- // Do not delete the Builder annotation here, we need it for @Jacksonized.
+ // Do not delete the Builder annotation yet, we need it for @Jacksonized.
JavacNode parent = annotationNode.up();
- java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- JCExpression returnType;
- List<JCTypeParameter> typeParams = List.nil();
- List<JCExpression> thrownExceptions = List.nil();
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ JCExpression buildMethodReturnType;
+ job.typeParams = List.nil();
+ List<JCExpression> buildMethodThrownExceptions;
Name nameOfBuilderMethod;
- JavacNode tdParent;
JavacNode fillParametersFrom = parent.get() instanceof JCMethodDecl ? parent : null;
boolean addCleaning = false;
- boolean isStatic = true;
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();
+ if (!isClass(parent) && !isRecord(parent)) {
+ annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ job.parentType = parent;
+ JCClassDecl td = (JCClassDecl) parent.get();
+
ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
- for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ for (JavacNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
JCVariableDecl fd = (JCVariableDecl) fieldNode.get();
JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, false);
boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
@@ -189,7 +252,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = findCopyableAnnotations(fieldNode);
bfd.type = fd.vartype;
- bfd.singularData = getSingularData(fieldNode, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -211,28 +274,30 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (isDefault != null) {
- bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name);
- bfd.nameOfSetFlag = parent.toName(bfd.name + "$set");
- bfd.builderFieldName = parent.toName(bfd.name + "$value");
+ bfd.nameOfDefaultProvider = parent.toName(DEFAULT_PREFIX + bfd.name);
+ bfd.nameOfSetFlag = parent.toName(bfd.name + SET_PREFIX);
+ bfd.builderFieldName = parent.toName(bfd.name + VALUE_PREFIX);
JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams);
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- if (md != null) injectMethod(tdParent, md);
+ recursiveSetGeneratedBy(md, annotationNode);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
allFields.append(fieldNode);
}
- if (!isRecord(tdParent)) {
- handleConstructor.generateConstructor(tdParent, 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);
}
- returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams);
- typeParams = td.typarams;
- thrownExceptions = List.nil();
+ buildMethodReturnType = namePlusTypeParamsToTypeReference(parent.getTreeMaker(), parent, td.typarams);
+ job.typeParams = job.builderTypeParams = td.typarams;
+ buildMethodThrownExceptions = List.nil();
nameOfBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
- replaceNameInBuilderClassName = false;
+ job.builderClassName = job.replaceBuilderClassName(td.name);
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (fillParametersFrom != null && fillParametersFrom.getName().toString().equals("<init>")) {
JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
if (!jmd.typarams.isEmpty()) {
@@ -240,38 +305,35 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return;
}
- tdParent = parent.up();
- JCClassDecl td = (JCClassDecl) tdParent.get();
- returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), tdParent, td.typarams);
- typeParams = td.typarams;
- thrownExceptions = jmd.thrown;
+ job.parentType = parent.up();
+ JCClassDecl td = (JCClassDecl) job.parentType.get();
+ job.typeParams = job.builderTypeParams = td.typarams;
+ buildMethodReturnType = job.createBuilderParentTypeReference();
+ buildMethodThrownExceptions = jmd.thrown;
nameOfBuilderMethod = null;
- if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
- replaceNameInBuilderClassName = false;
+ job.builderClassName = job.replaceBuilderClassName(td.name);
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
} else if (fillParametersFrom != null) {
- tdParent = parent.up();
- JCClassDecl td = (JCClassDecl) tdParent.get();
+ job.parentType = parent.up();
+ JCClassDecl td = (JCClassDecl) job.parentType.get();
JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
- isStatic = (jmd.mods.flags & Flags.STATIC) != 0;
+ job.isStatic = (jmd.mods.flags & Flags.STATIC) != 0;
+
JCExpression fullReturnType = jmd.restype;
- returnType = fullReturnType;
- typeParams = jmd.typarams;
- thrownExceptions = jmd.thrown;
+ buildMethodReturnType = fullReturnType;
+ job.typeParams = job.builderTypeParams = jmd.typarams;
+ buildMethodThrownExceptions = jmd.thrown;
nameOfBuilderMethod = jmd.name;
- if (returnType instanceof JCTypeApply) {
- returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext());
+ if (buildMethodReturnType instanceof JCTypeApply) {
+ buildMethodReturnType = cloneType(job.getTreeMaker(), buildMethodReturnType, annotationNode);
}
- if (replaceNameInBuilderClassName) {
- String replStr = returnTypeToBuilderClassName(annotationNode, td, returnType, typeParams);
- if (replStr == null)
- return;
- builderClassName = builderClassName.replace("*", replStr);
- replaceNameInBuilderClassName = false;
+ if (job.builderClassName.indexOf('*') > -1) {
+ String replStr = returnTypeToBuilderClassName(annotationNode, td, buildMethodReturnType, job.typeParams);
+ if (replStr == null) return; // shuold not happen
+ job.builderClassName = job.builderClassName.replace("*", replStr);
}
- 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) {
+ if (job.toBuilder) {
+ if (fullReturnType instanceof JCArrayTypeTree) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
@@ -284,8 +346,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
tpOnRet = ((JCTypeApply) fullReturnType).arguments;
}
- JCExpression namingType = returnType;
- if (returnType instanceof JCTypeApply) namingType = ((JCTypeApply) returnType).clazz;
+ JCExpression namingType = fullReturnType;
+ if (buildMethodReturnType instanceof JCTypeApply) namingType = ((JCTypeApply) buildMethodReturnType).clazz;
if (namingType instanceof JCIdent) {
simpleName = ((JCIdent) namingType).name;
@@ -309,13 +371,13 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return;
}
- if (!tdParent.getName().contentEquals(simpleName)) {
+ if (!job.parentType.getName().contentEquals(simpleName)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
List<JCTypeParameter> tpOnMethod = jmd.typarams;
- List<JCTypeParameter> tpOnType = ((JCClassDecl) tdParent.get()).typarams;
+ List<JCTypeParameter> tpOnType = ((JCClassDecl) job.parentType.get()).typarams;
typeArgsForToBuilder = new ArrayList<Name>();
for (JCTypeParameter tp : tpOnMethod) {
@@ -336,7 +398,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;
}
@@ -351,41 +413,41 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
bfd.rawName = raw.name;
bfd.annotations = findCopyableAnnotations(param);
bfd.type = raw.vartype;
- bfd.singularData = getSingularData(param, builderInstance.setterPrefix());
+ bfd.singularData = getSingularData(param, annInstance.setterPrefix());
bfd.originalFieldNode = param;
addObtainVia(bfd, param);
- builderFields.add(bfd);
+ job.builderFields.add(bfd);
}
}
- JavacNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = makeBuilderClass(isStatic, annotationNode, tdParent, builderClassName, typeParams, ast, accessForOuters);
- recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext());
+ job.builderType = findInnerClass(job.parentType, job.builderClassName);
+ if (job.builderType == null) {
+ job.builderType = makeBuilderClass(job);
+ recursiveSetGeneratedBy(job.builderType.get(), annotationNode);
} else {
- JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get();
- if (isStatic && !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
+ JCClassDecl builderTypeDeclaration = (JCClassDecl) job.builderType.get();
+ if (job.isStatic && !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
annotationNode.addError("Existing Builder must be a static inner class.");
return;
- } else if (!isStatic && builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
+ } else if (!job.isStatic && builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
annotationNode.addError("Existing Builder must be a non-static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderType, annotationNode);
/* generate errors for @Singular BFDs that have one already defined node. */ {
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
SingularData sd = bfd.singularData;
if (sd == null) continue;
JavacSingularizer singularizer = sd.getSingularizer();
if (singularizer == null) continue;
- if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderType, sd)) {
bfd.singularData = null;
}
}
}
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
@@ -404,75 +466,75 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
}
- generateBuilderFields(builderType, builderFields, ast);
+ generateBuilderFields(job);
if (addCleaning) {
- JavacTreeMaker maker = builderType.getTreeMaker();
- JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null);
- injectFieldAndMarkGenerated(builderType, uncleanField);
- recursiveSetGeneratedBy(uncleanField, ast, annotationNode.getContext());
+ JavacTreeMaker maker = job.getTreeMaker();
+ JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), job.builderType.toName(CLEAN_FIELD_NAME), maker.TypeIdent(CTC_BOOLEAN), null);
+ injectFieldAndMarkGenerated(job.builderType, uncleanField);
+ recursiveSetGeneratedBy(uncleanField, annotationNode);
}
- if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), false, annotationNode);
- if (cd != null) injectMethod(builderType, cd);
+ if (constructorExists(job.builderType) == MemberExistsResult.NOT_EXISTS) {
+ JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), job.builderType, List.<JavacNode>nil(), false, annotationNode);
+ if (cd != null) injectMethod(job.builderType, cd);
}
- for (BuilderFieldData bfd : builderFields) {
- makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, builderInstance.setterPrefix());
+ for (BuilderFieldData bfd : job.builderFields) {
+ makePrefixedSetterMethodsForBuilder(job, bfd, annInstance.setterPrefix());
}
{
- MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1);
- if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0);
+ MemberExistsResult methodExists = methodExists(job.buildMethodName, job.builderType, -1);
+ if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(job.buildMethodName, job.builderType, 0);
if (methodExists == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl md = generateBuildMethod(cfv, tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning, accessForInners);
+ JCMethodDecl md = generateBuildMethod(job, nameOfBuilderMethod, buildMethodReturnType, buildMethodThrownExceptions, addCleaning);
if (md != null) {
- injectMethod(builderType, md);
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
+ recursiveSetGeneratedBy(md, annotationNode);
+ injectMethod(job.builderType, md);
}
}
}
- if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
+ if (methodExists("toString", job.builderType, 0) == MemberExistsResult.NOT_EXISTS) {
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
for (JavacNode f : bfd.createdFields) {
fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false));
}
}
- JCMethodDecl md = HandleToString.createToString(builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, ast);
- if (md != null) injectMethod(builderType, md);
+ JCMethodDecl md = HandleToString.createToString(job.builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, job.sourceNode);
+ if (md != null) injectMethod(job.builderType, md);
}
- if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast));
+ if (addCleaning) injectMethod(job.builderType, generateCleanMethod(job));
- if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
if (generateBuilderMethod) {
- JCMethodDecl md = generateBuilderMethod(cfv, isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams, accessForOuters);
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- if (md != null) injectMethod(tdParent, md);
+ JCMethodDecl md = generateBuilderMethod(job);
+ recursiveSetGeneratedBy(md, annotationNode);
+ if (md != null) injectMethod(job.parentType, md);
}
- if (toBuilder) {
- switch (methodExists(toBuilderMethodName, tdParent, 0)) {
+ if (job.toBuilder) {
+ switch (methodExists(TO_BUILDER_METHOD_NAME, job.parentType, 0)) {
case EXISTS_BY_USER:
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
return;
case NOT_EXISTS:
- List<JCTypeParameter> tps = typeParams;
+ List<JCTypeParameter> tps = job.typeParams;
if (typeArgsForToBuilder != null) {
ListBuffer<JCTypeParameter> lb = new ListBuffer<JCTypeParameter>();
- JavacTreeMaker maker = tdParent.getTreeMaker();
+ JavacTreeMaker maker = job.getTreeMaker();
for (Name n : typeArgsForToBuilder) {
lb.append(maker.TypeParameter(n, List.<JCExpression>nil()));
}
tps = lb.toList();
}
- JCMethodDecl md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, isStatic, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix());
+ JCMethodDecl md = generateToBuilderMethod(job, tps, annInstance.setterPrefix());
if (md != null) {
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- injectMethod(tdParent, md);
+ recursiveSetGeneratedBy(md, annotationNode);
+ injectMethod(job.parentType, md);
}
}
}
@@ -553,47 +615,41 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
sb.append("__ERR__");
}
- private static final String BUILDER_TEMP_VAR = "builder";
- private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String toBuilderMethodName, String builderClassName, JavacNode type, boolean isStatic, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast, AccessLevel access, String prefix) {
+ private JCMethodDecl generateToBuilderMethod(BuilderJob job, List<JCTypeParameter> typeParameters, String prefix) {
// return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);
- JavacTreeMaker maker = type.getTreeMaker();
+ JavacTreeMaker maker = job.getTreeMaker();
- ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) {
- typeArgs.append(maker.Ident(typeParam.name));
- }
-
- JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCExpression>nil(), null);
+ 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;
ListBuffer<JCStatement> preStatements = null;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- for (BuilderFieldData bfd : builderFields) {
- String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set";
+ for (BuilderFieldData bfd : job.builderFields) {
+ String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set";
String prefixedSetterName = bfd.name.toString();
if (!setterPrefix.isEmpty()) prefixedSetterName = HandlerUtil.buildAccessorName(setterPrefix, prefixedSetterName);
- Name setterName = type.toName(prefixedSetterName);
+ Name setterName = job.toName(prefixedSetterName);
JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2];
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
for (int i = 0; i < tgt.length; i++) {
- tgt[i] = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field()));
+ tgt[i] = maker.Select(maker.Ident(job.toName("this")), bfd.obtainVia == null ? bfd.rawName : job.toName(bfd.obtainVia.field()));
}
} else {
String name = bfd.obtainVia.method();
JCMethodInvocation inv;
if (bfd.obtainVia.isStatic()) {
- JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(name));
- inv = maker.Apply(typeParameterNames(maker, typeParams), c, List.<JCExpression>of(maker.Ident(type.toName("this"))));
+ JCExpression c = maker.Select(maker.Ident(job.toName(job.parentType.getName())), job.toName(name));
+ inv = maker.Apply(typeParameterNames(maker, typeParameters), c, List.<JCExpression>of(maker.Ident(job.toName("this"))));
} else {
- JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(name));
+ JCExpression c = maker.Select(maker.Ident(job.toName("this")), job.toName(name));
inv = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil());
}
for (int i = 0; i < tgt.length; i++) tgt[i] = maker.Ident(bfd.name);
// javac appears to cache the type of JCMethodInvocation expressions based on position, meaning, if you have 2 ObtainVia-based method invokes on different types, you get bizarre type mismatch errors.
// going via a local variable declaration solves the problem.
- JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, ast, type.getContext());
+ JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, job.sourceNode);
if (preStatements == null) preStatements = new ListBuffer<JCStatement>();
preStatements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), bfd.name, varType, inv));
}
@@ -604,15 +660,15 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
invoke = maker.Apply(List.<JCExpression>nil(), maker.Select(invoke, setterName), List.of(arg));
} else {
JCExpression isNotNull = maker.Binary(CTC_NOT_EQUAL, tgt[0], maker.Literal(CTC_BOT, null));
- JCExpression invokeBuilder = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(type.toName(BUILDER_TEMP_VAR)), setterName), List.<JCExpression>of(tgt[1]));
+ JCExpression invokeBuilder = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(job.toName(BUILDER_TEMP_VAR)), setterName), List.<JCExpression>of(tgt[1]));
statements.append(maker.If(isNotNull, maker.Exec(invokeBuilder), null));
}
}
if (!statements.isEmpty()) {
- JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams);
- statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), type.toName(BUILDER_TEMP_VAR), tempVarType, invoke));
- statements.append(maker.Return(maker.Ident(type.toName(BUILDER_TEMP_VAR))));
+ JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, typeParameters);
+ statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), job.toName(BUILDER_TEMP_VAR), tempVarType, invoke));
+ statements.append(maker.Return(maker.Ident(job.toName(BUILDER_TEMP_VAR))));
} else {
statements.append(maker.Return(invoke));
}
@@ -622,77 +678,78 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
statements = preStatements;
}
JCBlock body = maker.Block(0, statements.toList());
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ List<JCAnnotation> annsOnParamType = List.nil();
+ if (job.checkerFramework.generateUnique()) annsOnParamType = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(job.accessOuters)), job.toName(TO_BUILDER_METHOD_NAME), namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, typeParameters, annsOnParamType), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
- private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateCleanMethod(BuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, type, source, statements);
+ bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, job.builderType, job.sourceNode, statements);
}
}
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)), maker.Literal(CTC_BOOLEAN, 0))));
JCBlock body = maker.Block(0, statements.toList());
- JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- recursiveSetGeneratedBy(method, source, type.getContext());
+ JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), job.toName(CLEAN_METHOD_NAME), maker.Type(Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ recursiveSetGeneratedBy(method, job.sourceNode);
return method;
}
- static List<JCVariableDecl> generateBuildArgs(CheckerFrameworkVersion cfv, JavacNode type, java.util.List<BuilderFieldData> builderFields) {
- if (!cfv.generateCalledMethods()) return List.<JCVariableDecl>nil();
-
+ static JCVariableDecl generateReceiver(BuilderJob job) {
+ if (!job.checkerFramework.generateCalledMethods()) return null;
+
ArrayList<String> mandatories = new ArrayList<String>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData == null && bfd.nameOfSetFlag == null) mandatories.add(bfd.name.toString());
}
-
+
JCExpression arg;
- JavacTreeMaker maker = type.getTreeMaker();
- if (mandatories.size() == 0) return List.<JCVariableDecl>nil();
+ JavacTreeMaker maker = job.getTreeMaker();
+ if (mandatories.size() == 0) return null;
if (mandatories.size() == 1) arg = maker.Literal(mandatories.get(0));
else {
List<JCExpression> elems = List.nil();
for (int i = mandatories.size() - 1; i >= 0; i--) elems = elems.prepend(maker.Literal(mandatories.get(i)));
arg = maker.NewArray(null, List.<JCExpression>nil(), elems);
}
- JCAnnotation recvAnno = maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__CALLED), List.of(arg));
- JCClassDecl builderTypeNode = (JCClassDecl) type.get();
- JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(recvAnno)), type.toName("this"), namePlusTypeParamsToTypeReference(maker, type, builderTypeNode.typarams), null);
- return List.of(recv);
+ JCAnnotation recvAnno = maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__CALLED), List.of(arg));
+ JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get();
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(Flags.PARAMETER, List.<JCAnnotation>nil()), job.toName("this"), namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(recvAnno)), null);
+ return recv;
}
- private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning, AccessLevel access) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateBuildMethod(BuilderJob job, Name staticName, JCExpression returnType, List<JCExpression> thrownExceptions, boolean addCleaning) {
+ JavacTreeMaker maker = job.getTreeMaker();
JCExpression call;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
if (addCleaning) {
- JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")));
- JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName("$lombokClean")), List.<JCExpression>nil()));
+ JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)));
+ JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(CLEAN_METHOD_NAME)), List.<JCExpression>nil()));
JCIf ifUnclean = maker.If(notClean, invokeClean, null);
statements.append(ifUnclean);
}
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.builderFieldName, "this");
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, job.builderType, job.sourceNode, statements, bfd.builderFieldName, "this");
}
}
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
- Name thisName = type.toName("this");
- for (BuilderFieldData bfd : builderFields) {
+ Name thisName = job.toName("this");
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.nameOfSetFlag != null) {
- statements.append(maker.VarDef(maker.Modifiers(0L), bfd.builderFieldName, cloneType(maker, bfd.type, source, tdParent.getContext()), maker.Select(maker.Ident(thisName), bfd.builderFieldName)));
- statements.append(maker.If(maker.Unary(CTC_NOT, maker.Select(maker.Ident(thisName), bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.builderFieldName), maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null));
+ statements.append(maker.VarDef(maker.Modifiers(0L), bfd.builderFieldName, cloneType(maker, bfd.type, job.sourceNode), maker.Select(maker.Ident(thisName), bfd.builderFieldName)));
+ statements.append(maker.If(maker.Unary(CTC_NOT, maker.Select(maker.Ident(thisName), bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.builderFieldName), maker.Apply(typeParameterNames(maker, ((JCClassDecl) job.parentType.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) job.parentType.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null));
}
if (bfd.nameOfSetFlag != null || (bfd.singularData != null && bfd.singularData.getSingularizer().shadowedDuringBuild())) {
args.append(maker.Ident(bfd.builderFieldName));
@@ -702,20 +759,20 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (addCleaning) {
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 1))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(job.toName("this")), job.toName(CLEAN_FIELD_NAME)), maker.Literal(CTC_BOOLEAN, 1))));
}
- if (builderName == null) {
+ if (staticName == null) {
call = maker.NewClass(null, List.<JCExpression>nil(), returnType, args.toList(), null);
statements.append(maker.Return(call));
} else {
ListBuffer<JCExpression> typeParams = new ListBuffer<JCExpression>();
- for (JCTypeParameter tp : ((JCClassDecl) type.get()).typarams) {
+ for (JCTypeParameter tp : ((JCClassDecl) job.builderType.get()).typarams) {
typeParams.append(maker.Ident(tp.name));
}
- JCExpression callee = maker.Ident(((JCClassDecl) type.up().get()).name);
- if (!isStatic) callee = maker.Select(callee, type.up().toName("this"));
- JCExpression fn = maker.Select(callee, builderName);
+ JCExpression callee = maker.Ident(((JCClassDecl) job.parentType.get()).name);
+ if (!job.isStatic) callee = maker.Select(callee, job.toName("this"));
+ JCExpression fn = maker.Select(callee, staticName);
call = maker.Apply(typeParams.toList(), fn, args.toList());
if (returnType instanceof JCPrimitiveTypeTree && CTC_VOID.equals(typeTag(returnType))) {
statements.append(maker.Exec(call));
@@ -726,10 +783,15 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JCBlock body = maker.Block(0, statements.toList());
- List<JCAnnotation> annsOnMethod = cfv.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
- List<JCVariableDecl> params = generateBuildArgs(cfv, type, builderFields);
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), params, thrownExceptions, body, null);
- if (builderName == null) createRelevantNonNullAnnotation(type, methodDef);
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ JCVariableDecl recv = generateReceiver(job);
+ JCMethodDecl methodDef;
+ if (recv != null && maker.hasMethodDefWithRecvParam()) {
+ methodDef = maker.MethodDefWithRecvParam(maker.Modifiers(toJavacModifier(job.accessInners), annsOnMethod), job.toName(job.buildMethodName), returnType, List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ } else {
+ methodDef = maker.MethodDef(maker.Modifiers(toJavacModifier(job.accessInners), annsOnMethod), job.toName(job.buildMethodName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ }
+ if (staticName == null) createRelevantNonNullAnnotation(job.builderType, methodDef);
return methodDef;
}
@@ -742,55 +804,56 @@ 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()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, fieldNode), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
- public JCMethodDecl generateBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) {
- JavacTreeMaker maker = type.getTreeMaker();
+ public JCMethodDecl generateBuilderMethod(BuilderJob job) {
+ //String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams, AccessLevel access) {
+ //builderClassName, annotationNode, tdParent, typeParams, accessForOuters);
- ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) {
- typeArgs.append(maker.Ident(typeParam.name));
- }
+ JavacTreeMaker maker = job.getTreeMaker();
JCExpression call;
- if (isStatic) {
- call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, typeParams), List.<JCExpression>nil(), null);
+ if (job.isStatic) {
+ call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderClassName), false, job.typeParams), List.<JCExpression>nil(), null);
} else {
- call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, null, type.toName(builderClassName), false, typeParams), List.<JCExpression>nil(), null);
- ((JCNewClass) call).encl = maker.Ident(type.toName("this"));
+ call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, null, job.toName(job.builderClassName), false, job.typeParams), List.<JCExpression>nil(), null);
+ ((JCNewClass) call).encl = maker.Ident(job.toName("this"));
}
JCStatement statement = maker.Return(call);
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
- int modifiers = toJavacModifier(access);
- if (isStatic) modifiers |= Flags.STATIC;
- JCAnnotation annUnique = cfv.generateUnique() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()) : null;
- JCAnnotation annSef = cfv.generateSideEffectFree() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()) : null;
- List<JCAnnotation> annsOnMethod;
- if (annUnique != null && annSef != null) annsOnMethod = List.of(annUnique, annSef);
- else if (annUnique != null) annsOnMethod = List.of(annUnique);
- else if (annSef != null) annsOnMethod = List.of(annSef);
- else annsOnMethod = List.nil();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ int modifiers = toJavacModifier(job.accessOuters);
+ if (job.isStatic) modifiers |= Flags.STATIC;
+ List<JCAnnotation> annsOnMethod = List.nil();
+ if (job.checkerFramework.generateSideEffectFree()) annsOnMethod = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ List<JCAnnotation> annsOnParamType = List.nil();
+ if (job.checkerFramework.generateUnique()) annsOnParamType = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
+
+ JCExpression returnType = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), !job.isStatic, job.builderTypeParams, annsOnParamType);
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(job.builderMethodName), returnType, job.copyTypeParams(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
- public void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) {
- int len = builderFields.size();
+ public void generateBuilderFields(BuilderJob job) {
+ int len = job.builderFields.size();
java.util.List<JavacNode> existing = new ArrayList<JavacNode>();
- for (JavacNode child : builderType.down()) {
+ for (JavacNode child : job.builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
java.util.List<JCVariableDecl> generated = new ArrayList<JCVariableDecl>();
for (int i = len - 1; i >= 0; i--) {
- BuilderFieldData bfd = builderFields.get(i);
+ BuilderFieldData bfd = job.builderFields.get(i);
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
+ java.util.List<JavacNode> generateSingularFields = bfd.singularData.getSingularizer().generateFields(bfd.singularData, job.builderType, job.sourceNode);
+ for (JavacNode field : generateSingularFields) {
+ generated.add((JCVariableDecl) field.get());
+ }
+ bfd.createdFields.addAll(generateSingularFields);
} else {
JavacNode field = null, setFlag = null;
for (JavacNode exists : existing) {
@@ -798,40 +861,41 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (n.equals(bfd.builderFieldName)) field = exists;
if (n.equals(bfd.nameOfSetFlag)) setFlag = exists;
}
- JavacTreeMaker maker = builderType.getTreeMaker();
+ JavacTreeMaker maker = job.getTreeMaker();
if (field == null) {
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
- JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, source, builderType.getContext()), null);
- field = injectFieldAndMarkGenerated(builderType, newField);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, job.sourceNode), null);
+ field = injectFieldAndMarkGenerated(job.builderType, newField);
generated.add(newField);
}
if (setFlag == null && bfd.nameOfSetFlag != null) {
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null);
- injectFieldAndMarkGenerated(builderType, newField);
+ injectFieldAndMarkGenerated(job.builderType, newField);
generated.add(newField);
}
bfd.createdFields.add(field);
}
}
- for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext());
+ for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, job.sourceNode);
}
- public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access, String prefix) {
- boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
- if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- makePrefixedSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access, prefix);
+ public void makePrefixedSetterMethodsForBuilder(BuilderJob job, BuilderFieldData bfd, String prefix) {
+ boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
+ if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
+ makePrefixedSetterMethodForBuilder(job, bfd, deprecate, prefix);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access);
+ bfd.singularData.getSingularizer().generateMethods(job, bfd.singularData, deprecate);
}
}
- private void makePrefixedSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access, String prefix) {
- String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set";
- String setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString());
- Name setterName_ = builderType.toName(setterName);
+ private void makePrefixedSetterMethodForBuilder(BuilderJob job, BuilderFieldData bfd, boolean deprecate, String prefix) {
+ JavacNode fieldNode = bfd.createdFields.get(0);
+ String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set";
+ String setterName = HandlerUtil.buildAccessorName(setterPrefix, bfd.name.toString());
+ Name setterName_ = job.builderType.toName(setterName);
- for (JavacNode child : builderType.down()) {
+ for (JavacNode child : job.builderType.down()) {
if (child.getKind() != Kind.METHOD) continue;
JCMethodDecl methodDecl = (JCMethodDecl) child.get();
Name existingName = methodDecl.name;
@@ -840,47 +904,45 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JavacTreeMaker maker = fieldNode.getTreeMaker();
- List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
- JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, chain, source, methodAnns, annosOnParam);
- if (cfv.generateCalledMethods()) {
- JCAnnotation ncAnno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(newMethod.getName().toString())));
- JCClassDecl builderTypeNode = (JCClassDecl) builderType.get();
- JCExpression selfType = namePlusTypeParamsToTypeReference(maker, builderType, builderTypeNode.typarams);
- JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), selfType, null);
- newMethod.params = List.of(recv, newMethod.params.get(0));
- }
- recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext());
- if (source.up().getKind() == Kind.METHOD) {
- copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString());
+ List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode);
+ JCMethodDecl newMethod = null;
+ if (job.checkerFramework.generateCalledMethods() && maker.hasMethodDefWithRecvParam()) {
+ JCAnnotation ncAnno = maker.Annotation(genTypeRef(job.sourceNode, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(setterName.toString())));
+ JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get();
+ JCExpression selfType = namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(ncAnno));
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(Flags.PARAMETER, List.<JCAnnotation>nil()), job.builderType.toName("this"), selfType, null);
+ newMethod = HandleSetter.createSetterWithRecv(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations, recv);
+ }
+ if (newMethod == null) newMethod = HandleSetter.createSetter(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations);
+ recursiveSetGeneratedBy(newMethod, job.sourceNode);
+ if (job.sourceNode.up().getKind() == Kind.METHOD) {
+ copyJavadocFromParam(bfd.originalFieldNode.up(), newMethod, bfd.name.toString());
} else {
- copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true);
+ copyJavadoc(bfd.originalFieldNode, newMethod, CopyJavadoc.SETTER, true);
}
- injectMethod(builderType, newMethod);
+ injectMethod(job.builderType, newMethod);
}
private void copyJavadocFromParam(JavacNode from, JCMethodDecl to, String param) {
try {
JCCompilationUnit cu = ((JCCompilationUnit) from.top().get());
String methodComment = Javac.getDocComment(cu, from.get());
- if (methodComment == null) return;
-
- Pattern pattern = Pattern.compile("@param " + param + " (\\S|\\s)+?(?=^ ?@)", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
- Matcher matcher = pattern.matcher(methodComment);
- if (matcher.find()) {
- String newJavadoc = addReturnsThisIfNeeded(matcher.group());
- Javac.setDocComment(cu, to, newJavadoc);
- }
+ String newJavadoc = addReturnsThisIfNeeded(getParamJavadoc(methodComment, param));
+ Javac.setDocComment(cu, to, newJavadoc);
} catch (Exception ignore) {}
- }
-
- public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) {
- JavacTreeMaker maker = tdParent.getTreeMaker();
- int modifiers = toJavacModifier(access);
- if (isStatic) modifiers |= Flags.STATIC;
+ }
+
+ public JavacNode makeBuilderClass(BuilderJob job) {
+ //boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) {
+ //isStatic, annotationNode, tdParent, builderClassName, typeParams, ast, accessForOuters
+ JavacTreeMaker maker = job.getTreeMaker();
+ int modifiers = toJavacModifier(job.accessOuters);
+ if (job.isStatic) modifiers |= Flags.STATIC;
JCModifiers mods = maker.Modifiers(modifiers);
- JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderClassName), copyTypeParams(source, typeParams), null, List.<JCExpression>nil(), List.<JCTree>nil());
- return injectType(tdParent, builder);
+ JCClassDecl builder = maker.ClassDef(mods, job.getBuilderClassName(), job.copyTypeParams(), null, List.<JCExpression>nil(), List.<JCTree>nil());
+ recursiveSetGeneratedBy(builder, job.sourceNode);
+ return injectType(job.parentType, builder);
}
private void addObtainVia(BuilderFieldData bfd, JavacNode node) {
diff --git a/src/core/lombok/javac/handlers/HandleBuilderDefault.java b/src/core/lombok/javac/handlers/HandleBuilderDefault.java
index df5eebc9..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) {
@@ -55,6 +54,7 @@ public class HandleBuilderDefault extends JavacAnnotationHandler<Builder.Default
JCFieldAccess jfa = (JCFieldAccess) ast.annotationType;
if (jfa.selected instanceof JCIdent && ((JCIdent) jfa.selected).name.contentEquals("Builder") && jfa.name.contentEquals("Default")) {
JCFieldAccess newJfaSel = annotationNode.getTreeMaker().Select(annotationNode.getTreeMaker().Ident(annotationNode.toName("lombok")), ((JCIdent) jfa.selected).name);
+ recursiveSetGeneratedBy(newJfaSel, annotationNode);
jfa.selected = newJfaSel;
}
}
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/HandleBuilderRemove.java b/src/core/lombok/javac/handlers/HandleBuilderRemove.java
index 6e59b40f..a47ed6b0 100644
--- a/src/core/lombok/javac/handlers/HandleBuilderRemove.java
+++ b/src/core/lombok/javac/handlers/HandleBuilderRemove.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Project Lombok Authors.
+ * Copyright (C) 2020-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -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;
@@ -33,9 +31,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 HandleBuilderRemove extends JavacAnnotationHandler<Builder> {
@Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
diff --git a/src/core/lombok/javac/handlers/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java
index 4aa61764..785ebf8a 100644
--- a/src/core/lombok/javac/handlers/HandleCleanup.java
+++ b/src/core/lombok/javac/handlers/HandleCleanup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -32,8 +32,7 @@ import lombok.delombok.LombokOptionsFactory;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
@@ -52,7 +51,6 @@ import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
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.Name;
@@ -60,7 +58,7 @@ import com.sun.tools.javac.util.Name;
/**
* Handles the {@code lombok.Cleanup} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleCleanup extends JavacAnnotationHandler<Cleanup> {
@Override public void handle(AnnotationValues<Cleanup> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.CLEANUP_FLAG_USAGE, "@Cleanup");
@@ -129,10 +127,9 @@ public class HandleCleanup extends JavacAnnotationHandler<Cleanup> {
JCIf ifNotNullCleanup = maker.If(isNull, maker.Block(0, cleanupCall), null);
- Context context = annotationNode.getContext();
- JCBlock finalizer = recursiveSetGeneratedBy(maker.Block(0, List.<JCStatement>of(ifNotNullCleanup)), ast, context);
+ JCBlock finalizer = recursiveSetGeneratedBy(maker.Block(0, List.<JCStatement>of(ifNotNullCleanup)), annotationNode);
- newStatements.append(setGeneratedBy(maker.Try(setGeneratedBy(maker.Block(0, tryBlock.toList()), ast, context), List.<JCCatch>nil(), finalizer), ast, context));
+ newStatements.append(setGeneratedBy(maker.Try(setGeneratedBy(maker.Block(0, tryBlock.toList()), annotationNode), List.<JCCatch>nil(), finalizer), annotationNode));
if (blockNode instanceof JCBlock) {
((JCBlock)blockNode).stats = newStatements.toList();
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index 54a9f821..9c74ca0e 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2019 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -25,8 +25,6 @@ import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Type;
@@ -55,18 +53,17 @@ import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.LombokNode;
import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.delombok.LombokOptionsFactory;
import lombok.javac.Javac;
-import lombok.javac.JavacAST;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
+import lombok.spi.Provides;
public class HandleConstructor {
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleNoArgsConstructor extends JavacAnnotationHandler<NoArgsConstructor> {
private static final String NAME = NoArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@@ -88,7 +85,7 @@ public class HandleConstructor {
}
}
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleRequiredArgsConstructor extends JavacAnnotationHandler<RequiredArgsConstructor> {
private static final String NAME = RequiredArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@@ -138,7 +135,7 @@ public class HandleConstructor {
return fields.toList();
}
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleAllArgsConstructor extends JavacAnnotationHandler<AllArgsConstructor> {
private static final String NAME = AllArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@@ -264,11 +261,11 @@ public class HandleConstructor {
generateStaticConstructor(staticConstrRequired, typeNode, staticName, level, allToDefault, fields, source, argTypes_);
}
- private void generateStaticConstructor(boolean staticConstrRequired, JavacNode typeNode, String staticName, AccessLevel level, boolean allToDefault, List<JavacNode> fields, LombokNode<JavacAST, JavacNode, JCTree> source, List<Type> argTypes_) {
+ private void generateStaticConstructor(boolean staticConstrRequired, JavacNode typeNode, String staticName, AccessLevel level, boolean allToDefault, List<JavacNode> fields, JavacNode source, List<Type> argTypes_) {
if (staticConstrRequired) {
ClassSymbol sym = ((JCClassDecl) typeNode.get()).sym;
Type returnType = sym == null ? null : sym.type;
- JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, allToDefault ? List.<JavacNode>nil() : fields, source.get());
+ JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, allToDefault ? List.<JavacNode>nil() : fields, source);
injectMethod(typeNode, staticConstr, argTypes_, returnType);
}
}
@@ -337,7 +334,7 @@ public class HandleConstructor {
Name rawName = field.name;
List<JCAnnotation> copyableAnnotations = findCopyableAnnotations(fieldNode);
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
- JCExpression pType = cloneType(fieldNode.getTreeMaker(), field.vartype, source.get(), source.getContext());
+ JCExpression pType = cloneType(fieldNode.getTreeMaker(), field.vartype, source);
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, copyableAnnotations), fieldName, pType, null);
params.append(param);
if (hasNonNullAnnotations(fieldNode)) {
@@ -372,10 +369,9 @@ public class HandleConstructor {
addConstructorProperties(mods, typeNode, fieldsToParam);
}
if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor));
- if (getCheckerFrameworkVersion(source).generateUnique()) mods.annotations = mods.annotations.prepend(maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
- maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source.get(), typeNode.getContext());
+ maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source);
}
/**
@@ -446,12 +442,11 @@ public class HandleConstructor {
return true;
}
- public JCMethodDecl createStaticConstructor(String name, AccessLevel level, JavacNode typeNode, List<JavacNode> fields, JCTree source) {
+ public JCMethodDecl createStaticConstructor(String name, AccessLevel level, JavacNode typeNode, List<JavacNode> fields, JavacNode source) {
JavacTreeMaker maker = typeNode.getTreeMaker();
JCClassDecl type = (JCClassDecl) typeNode.get();
JCModifiers mods = maker.Modifiers(Flags.STATIC | toJavacModifier(level));
- if (getCheckerFrameworkVersion(typeNode).generateUnique()) mods.annotations = mods.annotations.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
JCExpression returnType, constructorType;
@@ -464,13 +459,15 @@ public class HandleConstructor {
typeParams.append(maker.TypeParameter(param.name, param.bounds));
}
}
- returnType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams);
+ List<JCAnnotation> annsOnReturnType = List.nil();
+ if (getCheckerFrameworkVersion(typeNode).generateUnique()) annsOnReturnType = List.of(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
+ returnType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams, annsOnReturnType);
constructorType = namePlusTypeParamsToTypeReference(maker, typeNode, type.typarams);
for (JavacNode fieldNode : fields) {
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
Name fieldName = removePrefixFromField(fieldNode);
- JCExpression pType = cloneType(maker, field.vartype, source, typeNode.getContext());
+ JCExpression pType = cloneType(maker, field.vartype, source);
List<JCAnnotation> copyableAnnotations = findCopyableAnnotations(fieldNode);
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, copyableAnnotations), fieldName, pType, null);
@@ -482,6 +479,6 @@ public class HandleConstructor {
JCMethodDecl methodDef = maker.MethodDef(mods, typeNode.toName(name), returnType, typeParams.toList(), params.toList(), List.<JCExpression>nil(), body, null);
createRelevantNonNullAnnotation(typeNode, methodDef);
- return recursiveSetGeneratedBy(methodDef, source, typeNode.getContext());
+ return recursiveSetGeneratedBy(methodDef, source);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java
index 15c9c9e7..06524aa8 100644
--- a/src/core/lombok/javac/handlers/HandleData.java
+++ b/src/core/lombok/javac/handlers/HandleData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 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
@@ -30,8 +30,7 @@ import lombok.core.AnnotationValues;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.util.List;
@@ -39,7 +38,7 @@ import com.sun.tools.javac.util.List;
/**
* Handles the {@code lombok.Data} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleData extends JavacAnnotationHandler<Data> {
private HandleConstructor handleConstructor = new HandleConstructor();
private HandleGetter handleGetter = new HandleGetter();
@@ -52,9 +51,8 @@ public class HandleData extends JavacAnnotationHandler<Data> {
deleteAnnotationIfNeccessary(annotationNode, Data.class);
JavacNode typeNode = annotationNode.up();
- boolean notAClass = !isClass(typeNode);
- if (notAClass) {
+ if (!isClass(typeNode)) {
annotationNode.addError("@Data is only supported on a class.");
return;
}
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index d6e76ab1..4d72eea3 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -43,8 +43,6 @@ import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.tools.javac.code.Attribute.Compound;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
@@ -81,8 +79,10 @@ import lombok.javac.JavacResolution;
import lombok.javac.JavacResolution.TypeNotConvertibleException;
import lombok.javac.JavacTreeMaker;
import lombok.javac.ResolutionResetNeeded;
+import lombok.permit.Permit;
+import lombok.spi.Provides;
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(HandleDelegate.HANDLE_DELEGATE_PRIORITY) //2^16; to make sure that we also delegate generated methods.
@ResolutionResetNeeded
public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
@@ -348,7 +348,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
JCStatement body = useReturn ? maker.Return(delegateCall) : maker.Exec(delegateCall);
JCBlock bodyBlock = maker.Block(0, com.sun.tools.javac.util.List.of(body));
- return recursiveSetGeneratedBy(maker.MethodDef(mods, sig.name, returnType, toList(typeParams), toList(params), toList(thrown), bodyBlock, null), annotation.get(), annotation.getContext());
+ return recursiveSetGeneratedBy(maker.MethodDef(mods, sig.name, returnType, toList(typeParams), toList(params), toList(thrown), bodyBlock, null), annotation);
}
public static <T> com.sun.tools.javac.util.List<T> toList(ListBuffer<T> collection) {
@@ -466,7 +466,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
static {
Method m = null;
try {
- m = Type.class.getDeclaredMethod("unannotatedType");
+ m = Permit.getMethod(Type.class, "unannotatedType");
} catch (Exception e) {/* ignore */}
unannotated = m;
}
@@ -474,7 +474,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
static Type unannotatedType(Type t) {
if (unannotated == null) return t;
try {
- return (Type) unannotated.invoke(t);
+ return (Type) Permit.invoke(unannotated, t);
} catch (Exception e) {
return t;
}
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index e35deb5b..ffe882d8 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.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
@@ -30,11 +30,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
import com.sun.tools.javac.tree.JCTree.JCBinary;
@@ -42,6 +39,8 @@ import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
+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.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
@@ -56,6 +55,7 @@ import com.sun.tools.javac.util.Name;
import lombok.ConfigurationKeys;
import lombok.EqualsAndHashCode;
+import lombok.EqualsAndHashCode.CacheStrategy;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.configuration.CallSuperType;
@@ -68,19 +68,22 @@ import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
+import lombok.spi.Provides;
/**
* Handles the {@code lombok.EqualsAndHashCode} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHashCode> {
private static final String RESULT_NAME = "result";
private static final String PRIME_NAME = "PRIME";
+ private static final String HASH_CODE_CACHE_NAME = "$hashCodeCache";
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.EQUALS_AND_HASH_CODE_FLAG_USAGE, "@EqualsAndHashCode");
deleteAnnotationIfNeccessary(annotationNode, EqualsAndHashCode.class);
+ deleteImportFromCompilationUnit(annotationNode, CacheStrategy.class.getName());
EqualsAndHashCode ann = annotation.getInstance();
java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members = InclusionExclusionUtils.handleEqualsAndHashCodeMarking(annotationNode.up(), annotation, annotationNode);
JavacNode typeNode = annotationNode.up();
@@ -93,7 +96,9 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
- generateMethods(typeNode, annotationNode, members, callSuper, true, fieldAccess, onParam);
+ boolean cacheHashCode = ann.cacheStrategy() == CacheStrategy.LAZY;
+
+ generateMethods(typeNode, annotationNode, members, callSuper, true, cacheHashCode, fieldAccess, onParam);
}
public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode source) {
@@ -107,11 +112,11 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members = InclusionExclusionUtils.handleEqualsAndHashCodeMarking(typeNode, null, null);
- generateMethods(typeNode, source, members, null, false, access, List.<JCAnnotation>nil());
+ generateMethods(typeNode, source, members, null, false, false, access, List.<JCAnnotation>nil());
}
public void generateMethods(JavacNode typeNode, JavacNode source, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members,
- Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<JCAnnotation> onParam) {
+ Boolean callSuper, boolean whineIfExists, boolean cacheHashCode, FieldAccess fieldAccess, List<JCAnnotation> onParam) {
if (!isClass(typeNode)) {
source.addError("@EqualsAndHashCode is only supported on a class.");
@@ -129,30 +134,6 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
boolean isDirectDescendantOfObject = isDirectDescendantOfObject(typeNode);
- if (isDirectDescendantOfObject && callSuper) {
- source.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
- return;
- }
-
- if (implicitCallSuper && !isDirectDescendantOfObject) {
- CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_CALL_SUPER);
- if (cst == null) cst = CallSuperType.WARN;
-
- switch (cst) {
- default:
- case WARN:
- source.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
- callSuper = false;
- break;
- case SKIP:
- callSuper = false;
- break;
- case CALL:
- callSuper = true;
- break;
- }
- }
-
boolean isFinal = (((JCClassDecl) typeNode.get()).mods.flags & Flags.FINAL) != 0;
boolean needsCanEqual = !isFinal || !isDirectDescendantOfObject;
MemberExistsResult equalsExists = methodExists("equals", typeNode, 1);
@@ -181,26 +162,72 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
//fallthrough
}
- JCMethodDecl equalsMethod = createEquals(typeNode, members, callSuper, fieldAccess, needsCanEqual, source.get(), onParam);
+ if (isDirectDescendantOfObject && callSuper) {
+ source.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
+ return;
+ }
+
+ if (implicitCallSuper && !isDirectDescendantOfObject) {
+ CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_CALL_SUPER);
+ if (cst == null) cst = CallSuperType.WARN;
+
+ switch (cst) {
+ default:
+ case WARN:
+ source.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
+ callSuper = false;
+ break;
+ case SKIP:
+ callSuper = false;
+ break;
+ case CALL:
+ callSuper = true;
+ break;
+ }
+ }
+
+ JCMethodDecl equalsMethod = createEquals(typeNode, members, callSuper, fieldAccess, needsCanEqual, source, onParam);
injectMethod(typeNode, equalsMethod);
if (needsCanEqual && canEqualExists == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl canEqualMethod = createCanEqual(typeNode, source.get(), onParam);
+ JCMethodDecl canEqualMethod = createCanEqual(typeNode, source, onParam);
injectMethod(typeNode, canEqualMethod);
}
- JCMethodDecl hashCodeMethod = createHashCode(typeNode, members, callSuper, fieldAccess, source.get());
+ if (cacheHashCode){
+ if (fieldExists(HASH_CODE_CACHE_NAME, typeNode) != MemberExistsResult.NOT_EXISTS) {
+ String msg = String.format("Not caching the result of hashCode: A field named %s already exists.", HASH_CODE_CACHE_NAME);
+ source.addWarning(msg);
+ cacheHashCode = false;
+ } else {
+ createHashCodeCacheField(typeNode, source);
+ }
+ }
+
+ JCMethodDecl hashCodeMethod = createHashCode(typeNode, members, callSuper, cacheHashCode, fieldAccess, source);
injectMethod(typeNode, hashCodeMethod);
}
+
+ private void createHashCodeCacheField(JavacNode typeNode, JavacNode source) {
+ JavacTreeMaker maker = typeNode.getTreeMaker();
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE | Flags.TRANSIENT);
+ JCVariableDecl hashCodeCacheField = maker.VarDef(mods, typeNode.toName(HASH_CODE_CACHE_NAME), maker.TypeIdent(CTC_INT), null);
+ injectFieldAndMarkGenerated(typeNode, hashCodeCacheField);
+ recursiveSetGeneratedBy(hashCodeCacheField, source);
+ }
- public JCMethodDecl createHashCode(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
+ public JCMethodDecl createHashCode(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, boolean cacheHashCode, FieldAccess fieldAccess, JavacNode source) {
JavacTreeMaker maker = typeNode.getTreeMaker();
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
- if (checkerFramework.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ if (cacheHashCode && checkerFramework.generatePure()) {
+ annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()));
+ } else if (checkerFramework.generateSideEffectFree()) {
+ annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ }
JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
JCExpression returnType = maker.TypeIdent(CTC_INT);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
@@ -211,6 +238,15 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
boolean isEmpty = members.isEmpty();
+ /* if (this.$hashCodeCache != 0) return this.$hashCodeCache; */ {
+ if (cacheHashCode) {
+ JCIdent receiver = maker.Ident(typeNode.toName("this"));
+ JCFieldAccess cacheHashCodeFieldAccess = maker.Select(receiver, typeNode.toName(HASH_CODE_CACHE_NAME));
+ JCExpression cacheNotZero = maker.Binary(CTC_NOT_EQUAL, cacheHashCodeFieldAccess, maker.Literal(CTC_INT, 0));
+ statements.append(maker.If(cacheNotZero, maker.Return(cacheHashCodeFieldAccess), null));
+ }
+ }
+
/* final int PRIME = X; */ {
if (!isEmpty) {
statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(HandlerUtil.primeForHashcode())));
@@ -228,7 +264,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
/* ... 1; */
init = maker.Literal(1);
}
- statements.append(maker.VarDef(maker.Modifiers(isEmpty ? finalFlag : 0), resultName, maker.TypeIdent(CTC_INT), init));
+ statements.append(maker.VarDef(maker.Modifiers(isEmpty && !cacheHashCode ? finalFlag : 0L), resultName, maker.TypeIdent(CTC_INT), init));
}
for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
@@ -300,13 +336,27 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
}
+ /*
+ * if (result == 0) result = Integer.MIN_VALUE;
+ * this.$hashCodeCache = result;
+ *
+ */ {
+ if (cacheHashCode) {
+ statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(resultName), maker.Literal(CTC_INT, 0)),
+ maker.Exec(maker.Assign(maker.Ident(resultName), genJavaLangTypeRef(typeNode, "Integer", "MIN_VALUE"))), null));
+
+ JCFieldAccess cacheHashCodeFieldAccess = maker.Select(maker.Ident(typeNode.toName("this")), typeNode.toName(HASH_CODE_CACHE_NAME));
+ statements.append(maker.Exec(maker.Assign(cacheHashCodeFieldAccess, maker.Ident(resultName))));
+ }
+ }
+
/* return result; */ {
statements.append(maker.Return(maker.Ident(resultName)));
}
JCBlock body = maker.Block(0, statements.toList());
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("hashCode"), returnType,
- List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source, typeNode.getContext());
+ List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source);
}
public JCExpressionStatement createResultCalculation(JavacNode typeNode, JCExpression expr) {
@@ -368,7 +418,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
return maker.TypeApply(expr, wildcards.toList());
}
- public JCMethodDecl createEquals(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source, List<JCAnnotation> onParam) {
+ public JCMethodDecl createEquals(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JavacNode source, List<JCAnnotation> onParam) {
JavacTreeMaker maker = typeNode.getTreeMaker();
Name oName = typeNode.toName("o");
@@ -502,10 +552,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
JCBlock body = maker.Block(0, statements.toList());
- return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext());
+ return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source);
}
- public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List<JCAnnotation> onParam) {
+ public JCMethodDecl createCanEqual(JavacNode typeNode, JavacNode source, List<JCAnnotation> onParam) {
/* protected boolean canEqual(final java.lang.Object other) {
* return other instanceof Outer.Inner.MyType;
* }
@@ -530,7 +580,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JCBlock body = maker.Block(0, List.<JCStatement>of(
maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode, false)))));
- return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext());
+ return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source);
}
public JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField,
diff --git a/src/core/lombok/javac/handlers/HandleExtensionMethod.java b/src/core/lombok/javac/handlers/HandleExtensionMethod.java
index 345c5f8e..dd565f72 100644
--- a/src/core/lombok/javac/handlers/HandleExtensionMethod.java
+++ b/src/core/lombok/javac/handlers/HandleExtensionMethod.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
@@ -28,6 +28,7 @@ import static lombok.javac.handlers.JavacResolver.*;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import javax.lang.model.element.ElementKind;
@@ -37,12 +38,13 @@ import lombok.core.HandlerPriority;
import lombok.experimental.ExtensionMethod;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.javac.JavacResolution;
+import lombok.spi.Provides;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
@@ -51,6 +53,7 @@ import com.sun.tools.javac.code.Type.ErrorType;
import com.sun.tools.javac.code.Type.ForAll;
import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCExpression;
@@ -61,7 +64,7 @@ import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
/**
* Handles the {@link ExtensionMethod} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(66560) // 2^16 + 2^10; we must run AFTER HandleVal which is at 2^16
public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMethod> {
@Override
@@ -148,8 +151,9 @@ public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMetho
@Override
public Void visitMethodInvocation(final MethodInvocationTree tree, final Void p) {
+ super.visitMethodInvocation(tree, p);
handleMethodCall((JCMethodInvocation) tree);
- return super.visitMethodInvocation(tree, p);
+ return null;
}
private void handleMethodCall(final JCMethodInvocation methodCall) {
@@ -166,13 +170,25 @@ public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMetho
JCExpression receiver = receiverOf(methodCall);
String methodName = methodNameOf(methodCall);
- if ("this".equals(methodName) || "super".equals(methodName)) return;
- Type resolvedMethodCall = CLASS_AND_METHOD.resolveMember(methodCallNode, methodCall);
- if (resolvedMethodCall == null) return;
- if (!suppressBaseMethods && !(resolvedMethodCall instanceof ErrorType)) return;
- Type receiverType = CLASS_AND_METHOD.resolveMember(methodCallNode, receiver);
- if (receiverType == null) return;
- if (receiverType.tsym.toString().endsWith(receiver.toString())) return;
+ if ("this".equals(receiver.toString()) || "this".equals(methodName) || "super".equals(methodName)) return;
+ Map<JCTree, JCTree> resolution = new JavacResolution(methodCallNode.getContext()).resolveMethodMember(methodCallNode);
+
+ JCTree resolvedMethodCall = resolution.get(methodCall);
+ if (resolvedMethodCall == null || resolvedMethodCall.type == null) return;
+ if (!suppressBaseMethods && !(resolvedMethodCall.type instanceof ErrorType)) return;
+
+ JCTree resolvedReceiver = resolution.get(receiver);
+ if (resolvedReceiver == null || resolvedReceiver.type == null) return;
+ Type receiverType = resolvedReceiver.type;
+
+ // Skip static method access
+ Symbol sym = null;
+ if (resolvedReceiver instanceof JCIdent) {
+ sym = ((JCIdent) resolvedReceiver).sym;
+ } else if (resolvedReceiver instanceof JCFieldAccess) {
+ sym = ((JCFieldAccess) resolvedReceiver).sym;
+ }
+ if (sym instanceof ClassSymbol) return;
Types types = Types.instance(annotationNode.getContext());
for (Extension extension : extensions) {
@@ -186,6 +202,7 @@ public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMetho
if (!types.isAssignable(receiverType, firstArgType)) continue;
methodCall.args = methodCall.args.prepend(receiver);
methodCall.meth = chainDotsString(annotationNode, extensionProvider.toString() + "." + methodName);
+ recursiveSetGeneratedBy(methodCall.meth, methodCallNode);
return;
}
}
diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
index c974bdb9..ebab67e3 100644
--- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2016 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
@@ -34,8 +34,7 @@ import lombok.experimental.PackagePrivate;
import lombok.javac.JavacASTAdapter;
import lombok.javac.JavacASTVisitor;
import lombok.javac.JavacNode;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
@@ -46,7 +45,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
/**
* Handles the {@code lombok.FieldDefaults} annotation for javac.
*/
-@ProviderFor(JavacASTVisitor.class)
+@Provides(JavacASTVisitor.class)
@HandlerPriority(-2048) //-2^11; to ensure @Value picks up on messing with the fields' 'final' state, run earlier.
public class HandleFieldDefaults extends JavacASTAdapter {
public boolean generateFieldDefaultsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean makeFinal, boolean checkForTypeLevelFieldDefaults) {
diff --git a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
index ec4015c7..f3c879d5 100644
--- a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
+++ b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2019 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
@@ -36,8 +36,7 @@ import lombok.experimental.FieldNameConstants;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
@@ -53,7 +52,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameConstants> {
private static final IdentifierName FIELDS = IdentifierName.valueOf("Fields");
@@ -78,7 +77,7 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
if (qualified.isEmpty()) {
errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing");
} else {
- createInnerTypeFieldNameConstants(typeNode, errorNode, errorNode.get(), level, qualified, asEnum, innerTypeName, uppercase);
+ createInnerTypeFieldNameConstants(typeNode, errorNode, level, qualified, asEnum, innerTypeName, uppercase);
}
}
@@ -133,7 +132,7 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded(), uppercase);
}
- private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, JCTree pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, IdentifierName innerTypeName, boolean uppercase) {
+ private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, IdentifierName innerTypeName, boolean uppercase) {
if (fields.isEmpty()) return;
JavacTreeMaker maker = typeNode.getTreeMaker();
@@ -146,7 +145,7 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
if (fieldsType == null) {
JCClassDecl innerType = maker.ClassDef(mods, fieldsName, List.<JCTypeParameter>nil(), null, List.<JCExpression>nil(), List.<JCTree>nil());
fieldsType = injectType(typeNode, innerType);
- recursiveSetGeneratedBy(innerType, pos, typeNode.getContext());
+ recursiveSetGeneratedBy(innerType, errorNode);
genConstr = true;
} else {
JCClassDecl builderTypeDeclaration = (JCClassDecl) fieldsType.get();
@@ -166,7 +165,7 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
JCModifiers genConstrMods = maker.Modifiers(Flags.GENERATEDCONSTR | (asEnum ? 0L : Flags.PRIVATE));
JCBlock genConstrBody = maker.Block(0L, List.<JCStatement>of(maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(typeNode.toName("super")), List.<JCExpression>nil()))));
JCMethodDecl c = maker.MethodDef(genConstrMods, typeNode.toName("<init>"), null, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), genConstrBody, null);
- recursiveSetGeneratedBy(c, pos, typeNode.getContext());
+ recursiveSetGeneratedBy(c, errorNode);
injectMethod(fieldsType, c);
}
@@ -187,9 +186,9 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
}
JCVariableDecl constantField = maker.VarDef(constantValueMods, fName, returnType, init);
injectField(fieldsType, constantField, false, true);
- setGeneratedBy(constantField, pos, typeNode.getContext());
+ setGeneratedBy(constantField, errorNode);
generated.add(constantField);
}
- for (JCVariableDecl cf : generated) recursiveSetGeneratedBy(cf, pos, typeNode.getContext());
+ for (JCVariableDecl cf : generated) recursiveSetGeneratedBy(cf, errorNode);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index 1b4d404b..8f6de9bb 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.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
@@ -43,8 +43,7 @@ import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.JavacTreeMaker.TypeTag;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
@@ -70,8 +69,10 @@ import com.sun.tools.javac.util.Name;
/**
* Handles the {@code lombok.Getter} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleGetter extends JavacAnnotationHandler<Getter> {
+ private static final String GETTER_NODE_NOT_SUPPORTED_ERR = "@Getter is only supported on a class, an enum, or a field.";
+
public void generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter, List<JCAnnotation> onMethod) {
if (checkForTypeLevelGetter) {
if (hasAnnotation(Getter.class, typeNode)) {
@@ -81,7 +82,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
}
if (!isClassOrEnum(typeNode)) {
- errorNode.addError("@Getter is only supported on a class, an enum, or a field.");
+ errorNode.addError(GETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -165,7 +166,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
JavacNode fieldNode, JavacNode source, boolean whineIfExists, boolean lazy, List<JCAnnotation> onMethod) {
if (fieldNode.getKind() != Kind.FIELD) {
- source.addError("@Getter is only supported on a class or a field.");
+ source.addError(GETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -213,14 +214,14 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
- injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), lazy, onMethod), List.<Type>nil(), getMirrorForFieldType(fieldNode));
+ injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source, lazy, onMethod), List.<Type>nil(), getMirrorForFieldType(fieldNode));
}
- public JCMethodDecl createGetter(long access, JavacNode field, JavacTreeMaker treeMaker, JCTree source, boolean lazy, List<JCAnnotation> onMethod) {
+ public JCMethodDecl createGetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, boolean lazy, List<JCAnnotation> onMethod) {
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
// Remember the type; lazy will change it
- JCExpression methodType = cloneType(treeMaker, copyType(treeMaker, fieldNode), source, field.getContext());
+ JCExpression methodType = cloneType(treeMaker, copyType(treeMaker, fieldNode), source);
// Generate the methodName; lazy will change the field type
Name methodName = field.toName(toGetterName(field));
@@ -261,9 +262,9 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
if (isFieldDeprecated(field)) annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
- methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source, field.getContext());
+ methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
- if (toClearOfMarkers != null) recursiveSetGeneratedBy(toClearOfMarkers, null, null);
+ if (toClearOfMarkers != null) recursiveSetGeneratedBy(toClearOfMarkers, null);
if (methodArgPos != null) {
for (int i = 0; i < methodArgPos.length; i++) {
((JCMethodInvocation) toClearOfMarkers).args.get(i).pos = methodArgPos[i];
@@ -274,10 +275,10 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
if (addSuppressWarningsUnchecked) {
ListBuffer<JCExpression> suppressions = new ListBuffer<JCExpression>();
if (!Boolean.FALSE.equals(field.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS))) {
- suppressions.add(treeMaker.Literal("all"));
+ suppressions.append(treeMaker.Literal("all"));
}
- suppressions.add(treeMaker.Literal("unchecked"));
- addAnnotation(decl.mods, field, source.pos, source, field.getContext(), "java.lang.SuppressWarnings", treeMaker.NewArray(null, List.<JCExpression>nil(), suppressions.toList()));
+ suppressions.append(treeMaker.Literal("unchecked"));
+ addAnnotation(decl.mods, field, source, "java.lang.SuppressWarnings", treeMaker.NewArray(null, List.<JCExpression>nil(), suppressions.toList()));
}
copyJavadoc(field, decl, CopyJavadoc.GETTER);
@@ -328,7 +329,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
TYPE_MAP = Collections.unmodifiableMap(m);
}
- public List<JCStatement> createLazyGetterBody(JavacTreeMaker maker, JavacNode fieldNode, JCTree source) {
+ public List<JCStatement> createLazyGetterBody(JavacTreeMaker maker, JavacNode fieldNode, JavacNode source) {
/*
java.lang.Object value = this.fieldName.get();
if (value == null) {
@@ -374,7 +375,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
/* java.lang.Object value = this.fieldName.get();*/ {
JCExpression valueVarType = genJavaLangTypeRef(fieldNode, "Object");
- statements.append(maker.VarDef(maker.Modifiers(0), valueName, valueVarType, callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD))));
+ statements.append(maker.VarDef(maker.Modifiers(0L), valueName, valueVarType, callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD))));
}
/* if (value == null) { */ {
@@ -441,8 +442,8 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
/* private final java.util.concurrent.atomic.AtomicReference<Object> fieldName = new java.util.concurrent.atomic.AtomicReference<Object>(); */ {
field.vartype = recursiveSetGeneratedBy(
- maker.TypeApply(chainDotsString(fieldNode, AR), List.<JCExpression>of(genJavaLangTypeRef(fieldNode, "Object"))), source, fieldNode.getContext());
- field.init = recursiveSetGeneratedBy(maker.NewClass(null, NIL_EXPRESSION, copyType(maker, field), NIL_EXPRESSION, null), source, fieldNode.getContext());
+ maker.TypeApply(chainDotsString(fieldNode, AR), List.<JCExpression>of(genJavaLangTypeRef(fieldNode, "Object"))), source);
+ field.init = recursiveSetGeneratedBy(maker.NewClass(null, NIL_EXPRESSION, copyType(maker, field), NIL_EXPRESSION, null), source);
}
return statements.toList();
diff --git a/src/core/lombok/javac/handlers/HandleHelper.java b/src/core/lombok/javac/handlers/HandleHelper.java
index 6f4361c1..35b0c4f2 100755
--- a/src/core/lombok/javac/handlers/HandleHelper.java
+++ b/src/core/lombok/javac/handlers/HandleHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2016 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -29,8 +29,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.TreeVisitor;
import com.sun.source.util.TreeScanner;
@@ -56,8 +54,9 @@ import lombok.experimental.Helper;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
+import lombok.spi.Provides;
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleHelper extends JavacAnnotationHandler<Helper> {
private List<JCStatement> getStatementsFromJcNode(JCTree tree) {
if (tree instanceof JCBlock) return ((JCBlock) tree).stats;
@@ -71,7 +70,7 @@ public class HandleHelper extends JavacAnnotationHandler<Helper> {
else throw new IllegalArgumentException("Can't set statements on node type: " + tree.getClass());
}
- @Override public void handle(AnnotationValues<Helper> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ @Override public void handle(AnnotationValues<Helper> annotation, JCAnnotation ast, final JavacNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.HELPER_FLAG_USAGE, "@Helper");
deleteAnnotationIfNeccessary(annotationNode, Helper.class);
@@ -120,6 +119,7 @@ public class HandleHelper extends JavacAnnotationHandler<Helper> {
JCIdent jci = (JCIdent) jcmi.meth;
if (Arrays.binarySearch(knownMethodNames_, jci.name.toString()) < 0) return;
jcmi.meth = maker.Select(maker.Ident(helperName), jci.name);
+ recursiveSetGeneratedBy(jcmi.meth, annotationNode);
helperUsed[0] = true;
}
};
@@ -144,6 +144,7 @@ public class HandleHelper extends JavacAnnotationHandler<Helper> {
JCExpression init = maker.NewClass(null, List.<JCExpression>nil(), maker.Ident(annotatedType_.name), List.<JCExpression>nil(), null);
JCExpression varType = maker.Ident(annotatedType_.name);
JCVariableDecl decl = maker.VarDef(maker.Modifiers(Flags.FINAL), helperName, varType, init);
+ recursiveSetGeneratedBy(decl, annotationNode);
newStatements.append(decl);
}
setStatementsOfJcNode(containingBlock.get(), newStatements.toList());
diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java
index 0aa02d1b..3ee0eec4 100644
--- a/src/core/lombok/javac/handlers/HandleJacksonized.java
+++ b/src/core/lombok/javac/handlers/HandleJacksonized.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Project Lombok Authors.
+ * Copyright (C) 2020-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,8 +24,6 @@ package lombok.javac.handlers;
import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-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;
@@ -49,13 +47,14 @@ import lombok.extern.jackson.Jacksonized;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
+import lombok.spi.Provides;
/**
* This (javac) handler deals with {@code @Jacksonized} modifying the (already
* generated) {@code @Builder} or {@code @SuperBuilder} to conform to Jackson's
* needs for builders.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(-512) // Above Handle(Super)Builder's level (builders must be already generated).
public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
@@ -107,7 +106,7 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
JavacTreeMaker maker = annotatedNode.getTreeMaker();
// Now lets find the generated builder class.
- String builderClassName = getBuilderClassName(ast, annotationNode, annotatedNode, td, builderAnnotation, maker);
+ String builderClassName = getBuilderClassName(annotationNode, annotatedNode, td, builderAnnotation, maker);
JCClassDecl builderClass = null;
for (JCTree member : td.getMembers()) {
@@ -132,11 +131,15 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
JCFieldAccess builderClassReference = maker.Select(builderClassExpression, annotatedNode.toName("class"));
JCExpression assign = maker.Assign(maker.Ident(annotationNode.toName("builder")), builderClassReference);
JCAnnotation annotationJsonDeserialize = maker.Annotation(jsonDeserializeType, List.of(assign));
+ recursiveSetGeneratedBy(annotationJsonDeserialize, annotationNode);
td.mods.annotations = td.mods.annotations.append(annotationJsonDeserialize);
// Copy annotations from the class to the builder class.
List<JCAnnotation> copyableAnnotations = findJacksonAnnotationsOnClass(tdNode);
List<JCAnnotation> copiedAnnotations = copyAnnotations(copyableAnnotations);
+ for (JCAnnotation anno : copiedAnnotations) {
+ recursiveSetGeneratedBy(anno, annotationNode);
+ }
builderClass.mods.annotations = builderClass.mods.annotations.appendList(copiedAnnotations);
// Insert @JsonPOJOBuilder on the builder class.
@@ -144,6 +147,7 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
JCExpression withPrefixExpr = maker.Assign(maker.Ident(annotationNode.toName("withPrefix")), maker.Literal(setPrefix));
JCExpression buildMethodNameExpr = maker.Assign(maker.Ident(annotationNode.toName("buildMethodName")), maker.Literal(buildMethodName));
JCAnnotation annotationJsonPOJOBuilder = maker.Annotation(jsonPOJOBuilderType, List.of(withPrefixExpr, buildMethodNameExpr));
+ recursiveSetGeneratedBy(annotationJsonPOJOBuilder, annotatedNode);
builderClass.mods.annotations = builderClass.mods.annotations.append(annotationJsonPOJOBuilder);
// @SuperBuilder? Make it package-private!
@@ -151,7 +155,7 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
builderClass.mods.flags = builderClass.mods.flags & ~Flags.PRIVATE;
}
- private String getBuilderClassName(JCAnnotation ast, JavacNode annotationNode, JavacNode annotatedNode, JCClassDecl td, AnnotationValues<Builder> builderAnnotation, JavacTreeMaker maker) {
+ private String getBuilderClassName(JavacNode annotationNode, JavacNode annotatedNode, JCClassDecl td, AnnotationValues<Builder> builderAnnotation, JavacTreeMaker maker) {
String builderClassName = builderAnnotation != null ?
builderAnnotation.getInstance().builderClassName() : null;
if (builderClassName == null || builderClassName.isEmpty()) {
@@ -166,7 +170,7 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
JCExpression returnType = fillParametersFrom.restype;
List<JCTypeParameter> typeParams = fillParametersFrom.typarams;
if (returnType instanceof JCTypeApply) {
- returnType = cloneType(maker, returnType, ast, annotationNode.getContext());
+ returnType = cloneType(maker, returnType, annotatedNode);
}
replacement = HandleBuilder.returnTypeToBuilderClassName(annotationNode, td, returnType, typeParams);
} else {
diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java
index 1ff10ad1..47c4098f 100644
--- a/src/core/lombok/javac/handlers/HandleLog.java
+++ b/src/core/lombok/javac/handlers/HandleLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2019 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -31,15 +31,14 @@ import lombok.core.configuration.IdentifierName;
import lombok.core.configuration.LogDeclaration;
import lombok.core.configuration.LogDeclaration.LogFactoryParameter;
import lombok.core.handlers.LoggingFramework;
+import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCExpression;
@@ -75,6 +74,7 @@ public class HandleLog {
annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
return;
}
+
if (isRecord(typeNode) && !useStatic) {
annotationNode.addError("Logger fields must be static in records.");
return;
@@ -82,7 +82,7 @@ public class HandleLog {
Object valueGuess = annotation.getValueGuess("topic");
JCExpression loggerTopic = (JCExpression) annotation.getActualExpression("topic");
-
+
if (valueGuess instanceof String && ((String) valueGuess).trim().isEmpty()) loggerTopic = null;
if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) {
annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic.");
@@ -94,7 +94,7 @@ public class HandleLog {
}
JCFieldAccess loggingType = selfType(typeNode);
- createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName.getName(), useStatic, loggerTopic);
+ createField(framework, typeNode, loggingType, annotationNode, logFieldName.getName(), useStatic, loggerTopic);
break;
default:
annotationNode.addError("@Log is legal only on types.");
@@ -108,7 +108,7 @@ public class HandleLog {
return maker.Select(maker.Ident(name), typeNode.toName("class"));
}
- private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, JCExpression loggerTopic) {
+ private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JavacNode source, String logFieldName, boolean useStatic, JCExpression loggerTopic) {
JavacTreeMaker maker = typeNode.getTreeMaker();
LogDeclaration logDeclaration = framework.getDeclaration();
@@ -122,17 +122,19 @@ public class HandleLog {
JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef(
maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)),
- typeNode.toName(logFieldName), loggerType, factoryMethodCall), source, typeNode.getContext());
+ typeNode.toName(logFieldName), loggerType, factoryMethodCall), source);
- // This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8243057
- if (isRecord(typeNode)) {
+ if (isRecord(typeNode) && Javac.getJavaCompilerVersion() < 16) {
+ // This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8243057
+
injectField(typeNode, fieldDecl);
} else {
injectFieldAndMarkGenerated(typeNode, fieldDecl);
}
+
return true;
}
-
+
private static JCExpression[] createFactoryParameters(JavacNode typeNode, JCFieldAccess loggingType, java.util.List<LogFactoryParameter> parameters, JCExpression loggerTopic) {
JCExpression[] expressions = new JCExpression[parameters.size()];
JavacTreeMaker maker = typeNode.getTreeMaker();
@@ -164,7 +166,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.apachecommons.CommonsLog} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleCommonsLog extends JavacAnnotationHandler<lombok.extern.apachecommons.CommonsLog> {
@Override public void handle(AnnotationValues<lombok.extern.apachecommons.CommonsLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -175,7 +177,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.java.Log} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleJulLog extends JavacAnnotationHandler<lombok.extern.java.Log> {
@Override public void handle(AnnotationValues<lombok.extern.java.Log> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -186,7 +188,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.log4j.Log4j} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleLog4jLog extends JavacAnnotationHandler<lombok.extern.log4j.Log4j> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -197,7 +199,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.log4j.Log4j2} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleLog4j2Log extends JavacAnnotationHandler<lombok.extern.log4j.Log4j2> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j2> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -208,7 +210,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.slf4j.Slf4j} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleSlf4jLog extends JavacAnnotationHandler<lombok.extern.slf4j.Slf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.Slf4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -219,7 +221,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.slf4j.XSlf4j} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleXSlf4jLog extends JavacAnnotationHandler<lombok.extern.slf4j.XSlf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.XSlf4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -230,7 +232,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.jbosslog.JBossLog} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleJBossLog extends JavacAnnotationHandler<lombok.extern.jbosslog.JBossLog> {
@Override public void handle(AnnotationValues<lombok.extern.jbosslog.JBossLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -241,7 +243,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.extern.flogger.Flogger} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleFloggerLog extends JavacAnnotationHandler<lombok.extern.flogger.Flogger> {
@Override public void handle(AnnotationValues<lombok.extern.flogger.Flogger> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_FLOGGER_FLAG_USAGE, "@Flogger", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
@@ -252,7 +254,7 @@ public class HandleLog {
/**
* Handles the {@link lombok.CustomLog} annotation for javac.
*/
- @ProviderFor(JavacAnnotationHandler.class)
+ @Provides
public static class HandleCustomLog extends JavacAnnotationHandler<lombok.CustomLog> {
@Override public void handle(AnnotationValues<lombok.CustomLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_CUSTOM_FLAG_USAGE, "@CustomLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java
index 6b6b7efa..2f359c0f 100644
--- a/src/core/lombok/javac/handlers/HandleNonNull.java
+++ b/src/core/lombok/javac/handlers/HandleNonNull.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2019 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
@@ -27,8 +27,6 @@ import static lombok.javac.JavacTreeMaker.TreeTag.treeTag;
import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
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.JCAssert;
import com.sun.tools.javac.tree.JCTree.JCAssign;
@@ -57,17 +55,16 @@ import lombok.NonNull;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
-
-import lombok.javac.Java14Flags;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists;
+import lombok.spi.Provides;
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first.
public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
private HandleConstructor handleConstructor = new HandleConstructor();
-
+
@Override public void handle(AnnotationValues<NonNull> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull");
@@ -117,7 +114,7 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
// and if they exist, create a new method in the class: 'private static <T> T lombok$nullCheck(T expr, String msg) {if (expr == null) throw NPE; return expr;}' and
// wrap all references to it in the super/this to a call to this method.
- JCStatement nullCheck = recursiveSetGeneratedBy(generateNullCheck(annotationNode.getTreeMaker(), paramNode, annotationNode), ast, annotationNode.getContext());
+ JCStatement nullCheck = recursiveSetGeneratedBy(generateNullCheck(annotationNode.getTreeMaker(), paramNode, annotationNode), annotationNode);
if (nullCheck == null) {
// @NonNull applied to a primitive. Kinda pointless. Let's generate a warning.
@@ -125,19 +122,18 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
return;
}
+ List<JCStatement> statements = declaration.body.stats;
+
+ String expectedName = paramNode.getName();
+
JavacNode typeNode = upToTypeNode(annotationNode);
- if ((declaration.mods.flags & Java14Flags.RECORD) != 0) {
- if (!lombokConstructorExists(typeNode)) {
+ if ((declaration.mods.flags & RECORD) != 0) {
+ if (!lombokConstructorExists(typeNode)) {
handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, null, SkipIfConstructorExists.NO, annotationNode);
}
- return;
}
- List<JCStatement> statements = declaration.body.stats;
-
- String expectedName = paramNode.getName();
-
/* Abort if the null check is already there, delving into try and synchronized statements */ {
List<JCStatement> stats = statements;
int idx = 0;
diff --git a/src/core/lombok/javac/handlers/HandlePrintAST.java b/src/core/lombok/javac/handlers/HandlePrintAST.java
index 0826d1d1..647139bc 100644
--- a/src/core/lombok/javac/handlers/HandlePrintAST.java
+++ b/src/core/lombok/javac/handlers/HandlePrintAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -25,8 +25,6 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import lombok.Lombok;
@@ -36,11 +34,12 @@ import lombok.core.PrintAST;
import lombok.javac.JavacASTVisitor;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
+import lombok.spi.Provides;
/**
* Handles the {@code lombok.core.PrintAST} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(536870912) // 2^29; this handler is customarily run at the very end.
public class HandlePrintAST extends JavacAnnotationHandler<PrintAST> {
@Override public void handle(AnnotationValues<PrintAST> annotation, JCAnnotation ast, JavacNode annotationNode) {
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index b51574b7..5c34f9f5 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.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
@@ -37,8 +37,7 @@ import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
@@ -60,8 +59,10 @@ import com.sun.tools.javac.util.Name;
/**
* Handles the {@code lombok.Setter} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleSetter extends JavacAnnotationHandler<Setter> {
+ private static final String SETTER_NODE_NOT_SUPPORTED_ERR = "@Setter is only supported on a class or a field.";
+
public void generateSetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelSetter, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (checkForTypeLevelSetter) {
if (hasAnnotation(Setter.class, typeNode)) {
@@ -71,7 +72,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
}
if (!isClass(typeNode)) {
- errorNode.addError("@Setter is only supported on a class or a field.");
+ errorNode.addError(SETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -145,7 +146,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
public void createSetterForField(AccessLevel level, JavacNode fieldNode, JavacNode sourceNode, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (fieldNode.getKind() != Kind.FIELD) {
- fieldNode.addError("@Setter is only supported on a class or a field.");
+ fieldNode.addError(SETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -215,13 +216,36 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
List<JCAnnotation> annotations = d.mods.annotations;
if (annotations == null) annotations = List.nil();
JCAnnotation anno = treeMaker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil());
- recursiveSetGeneratedBy(anno, source.get(), field.getContext());
+ recursiveSetGeneratedBy(anno, source);
+ d.mods.annotations = annotations.prepend(anno);
+ }
+ return d;
+ }
+
+ public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, JCVariableDecl recv) {
+ JCExpression returnType = null;
+ JCReturn returnStatement = null;
+ if (shouldReturnThis) {
+ returnType = cloneSelfType(field);
+ returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this")));
+ }
+
+ JCMethodDecl d = createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, recv);
+ if (shouldReturnThis && getCheckerFrameworkVersion(source).generateReturnsReceiver()) {
+ List<JCAnnotation> annotations = d.mods.annotations;
+ if (annotations == null) annotations = List.nil();
+ JCAnnotation anno = treeMaker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil());
+ recursiveSetGeneratedBy(anno, source);
d.mods.annotations = annotations.prepend(anno);
}
return d;
}
public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
+ return createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, methodType, returnStatement, source, onMethod, onParam, null);
+ }
+
+ public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, JCVariableDecl recv) {
if (setterName == null) return null;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
@@ -237,7 +261,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(copyableAnnotations);
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
- JCExpression pType = cloneType(treeMaker, fieldDecl.vartype, source.get(), source.getContext());
+ JCExpression pType = cloneType(treeMaker, fieldDecl.vartype, source);
JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(flags, annsOnParam), paramName, pType, null);
if (!hasNonNullAnnotations(field) && !hasNonNullAnnotations(field, onParam)) {
@@ -272,10 +296,16 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
}
- JCMethodDecl methodDef = treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
- methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
+ JCMethodDecl methodDef;
+ if (recv != null && treeMaker.hasMethodDefWithRecvParam()) {
+ methodDef = treeMaker.MethodDefWithRecvParam(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
+ methodGenericParams, recv, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
+ } else {
+ methodDef = treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
+ methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
+ }
if (returnStatement != null) createRelevantNonNullAnnotation(source, methodDef);
- JCMethodDecl decl = recursiveSetGeneratedBy(methodDef, source.get(), field.getContext());
+ JCMethodDecl decl = recursiveSetGeneratedBy(methodDef, source);
copyJavadoc(field, decl, CopyJavadoc.SETTER, returnStatement != null);
return decl;
}
diff --git a/src/core/lombok/javac/handlers/HandleSneakyThrows.java b/src/core/lombok/javac/handlers/HandleSneakyThrows.java
index ffe37a4c..3dde75d8 100644
--- a/src/core/lombok/javac/handlers/HandleSneakyThrows.java
+++ b/src/core/lombok/javac/handlers/HandleSneakyThrows.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -35,11 +35,9 @@ import lombok.core.HandlerPriority;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -48,14 +46,13 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTry;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
-import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import lombok.javac.Javac;
/**
* Handles the {@code lombok.SneakyThrows} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it.
public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> {
@Override public void handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) {
@@ -107,7 +104,7 @@ public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> {
}
for (String exception : exceptions) {
- contents = List.of(buildTryCatchBlock(methodNode, contents, exception, annotation.get()));
+ contents = List.of(buildTryCatchBlock(methodNode, contents, exception, annotation));
}
method.body.stats = isConstructorCall ? List.of(constructorCall).appendList(contents) : contents;
@@ -122,11 +119,10 @@ public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> {
}
}
- public JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception, JCTree source) {
+ public JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception, JavacNode source) {
JavacTreeMaker maker = node.getTreeMaker();
- Context context = node.getContext();
- JCBlock tryBlock = setGeneratedBy(maker.Block(0, contents), source, context);
+ JCBlock tryBlock = setGeneratedBy(maker.Block(0, contents), source);
JCExpression varType = chainDots(node, exception.split("\\."));
JCVariableDecl catchParam = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER), node.toName("$ex"), varType, null);
@@ -134,7 +130,7 @@ public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> {
JCBlock catchBody = maker.Block(0, List.<JCStatement>of(maker.Throw(maker.Apply(
List.<JCExpression>nil(), lombokLombokSneakyThrowNameRef,
List.<JCExpression>of(maker.Ident(node.toName("$ex")))))));
- JCTry tryStatement = maker.Try(tryBlock, List.of(recursiveSetGeneratedBy(maker.Catch(catchParam, catchBody), source, context)), null);
+ JCTry tryStatement = maker.Try(tryBlock, List.of(recursiveSetGeneratedBy(maker.Catch(catchParam, catchBody), source)), null);
if (JavacHandlerUtil.inNetbeansEditor(node)) {
//set span (start and end position) of the try statement and the main block
//this allows NetBeans to dive into the statement correctly:
@@ -146,6 +142,6 @@ public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> {
Javac.storeEnd(tryBlock, endPos, top);
Javac.storeEnd(tryStatement, endPos, top);
}
- return setGeneratedBy(tryStatement, source, context);
+ return setGeneratedBy(tryStatement, source);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
index be6ddae2..9185cedf 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.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
@@ -21,6 +21,7 @@
*/
package lombok.javac.handlers;
+import static lombok.javac.handlers.HandleBuilder.*;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
@@ -31,8 +32,6 @@ import java.util.HashSet;
import javax.lang.model.element.Modifier;
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
@@ -53,7 +52,6 @@ import com.sun.tools.javac.tree.JCTree.JCTypeApply;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
-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.Name;
@@ -78,68 +76,102 @@ import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.HandleBuilder.BuilderFieldData;
+import lombok.javac.handlers.HandleBuilder.BuilderJob;
import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker;
+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 HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
private static final String SELF_METHOD = "self";
- private static final String TO_BUILDER_METHOD_NAME = "toBuilder";
private static final String FILL_VALUES_METHOD_NAME = "$fillValuesFrom";
private static final String STATIC_FILL_VALUES_METHOD_NAME = "$fillValuesFromInstanceIntoBuilder";
private static final String INSTANCE_VARIABLE_NAME = "instance";
private static final String BUILDER_VARIABLE_NAME = "b";
-
+
+ class SuperBuilderJob extends BuilderJob {
+ JavacNode builderAbstractType;
+ String builderAbstractClassName;
+ JavacNode builderImplType;
+ String builderImplClassName;
+ List<JCTypeParameter> builderTypeParams_;
+
+ void init(AnnotationValues<SuperBuilder> annValues, SuperBuilder ann, JavacNode node) {
+ accessOuters = accessInners = AccessLevel.PUBLIC;
+ oldFluent = true;
+ oldChain = true;
+
+ builderMethodName = ann.builderMethodName();
+ buildMethodName = ann.buildMethodName();
+ toBuilder = ann.toBuilder();
+
+ if (builderMethodName == null) builderMethodName = "builder";
+ if (buildMethodName == null) buildMethodName = "build";
+ builderClassName = fixBuilderClassName(node, "");
+ }
+
+ void setBuilderToImpl() {
+ builderType = builderImplType;
+ builderClassName = builderImplClassName;
+ builderTypeParams = typeParams;
+ }
+
+ void setBuilderToAbstract() {
+ builderType = builderAbstractType;
+ builderClassName = builderAbstractClassName;
+ builderTypeParams = builderTypeParams_;
+ }
+ }
+
@Override
public void handle(AnnotationValues<SuperBuilder> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
- CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
- SuperBuilder superbuilderAnnotation = annotation.getInstance();
- // Do not delete the SuperBuilder annotation here, we need it for @Jacksonized.
+ SuperBuilderJob job = new SuperBuilderJob();
+ job.sourceNode = annotationNode;
+ job.checkerFramework = getCheckerFrameworkVersion(annotationNode);
+ job.isStatic = true;
- String builderMethodName = superbuilderAnnotation.builderMethodName();
- String buildMethodName = superbuilderAnnotation.buildMethodName();
+ SuperBuilder annInstance = annotation.getInstance();
- if (builderMethodName == null) builderMethodName = "builder";
- if (buildMethodName == null) buildMethodName = "build";
+ job.init(annotation, annInstance, annotationNode);
boolean generateBuilderMethod;
- if (builderMethodName.isEmpty()) {
+ if (job.builderMethodName.isEmpty()) {
generateBuilderMethod = false;
- } else if (!checkName("builderMethodName", builderMethodName, annotationNode)) {
+ } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) {
return;
} else {
generateBuilderMethod = true;
}
- if (!checkName("buildMethodName", buildMethodName, annotationNode)) return;
+ if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return;
- boolean toBuilder = superbuilderAnnotation.toBuilder();
+ // Do not delete the SuperBuilder annotation here, we need it for @Jacksonized.
- JavacNode tdParent = annotationNode.up();
+ JavacNode parent = annotationNode.up();
- java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
- List<JCTypeParameter> typeParams = List.nil();
- List<JCExpression> thrownExceptions = List.nil();
+ job.builderFields = new ArrayList<BuilderFieldData>();
+ job.typeParams = List.nil();
+ List<JCExpression> buildMethodThrownExceptions = List.nil();
List<JCExpression> superclassTypeParams = List.nil();
-
boolean addCleaning = false;
- if (!isClass(tdParent)) {
- annotationNode.addError("@SuperBuilder is only supported on types.");
+ if (!isClass(parent)) {
+ annotationNode.addError("@SuperBuilder is only supported on classes.");
return;
}
+ job.parentType = parent;
+ JCClassDecl td = (JCClassDecl) parent.get();
+
// Gather all fields of the class that should be set by the builder.
- JCClassDecl td = (JCClassDecl) tdParent.get();
- ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
ArrayList<JavacNode> nonFinalNonDefaultedFields = null;
- boolean valuePresent = (hasAnnotation(lombok.Value.class, tdParent) || hasAnnotation("lombok.experimental.Value", tdParent));
- for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
+ for (JavacNode fieldNode : HandleConstructor.findAllFields(parent, true)) {
JCVariableDecl fd = (JCVariableDecl) fieldNode.get();
JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, true);
boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
@@ -149,7 +181,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
bfd.builderFieldName = bfd.name;
bfd.annotations = findCopyableAnnotations(fieldNode);
bfd.type = fd.vartype;
- bfd.singularData = getSingularData(fieldNode, superbuilderAnnotation.setterPrefix());
+ bfd.singularData = getSingularData(fieldNode, annInstance.setterPrefix());
bfd.originalFieldNode = fieldNode;
if (bfd.singularData != null && isDefault != null) {
@@ -169,44 +201,20 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
if (isDefault != null) {
- bfd.nameOfDefaultProvider = tdParent.toName("$default$" + bfd.name);
- bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set");
- bfd.builderFieldName = tdParent.toName(bfd.name + "$value");
+ bfd.nameOfDefaultProvider = parent.toName(DEFAULT_PREFIX + bfd.name);
+ bfd.nameOfSetFlag = parent.toName(bfd.name + SET_PREFIX);
+ bfd.builderFieldName = parent.toName(bfd.name + VALUE_PREFIX);
JCMethodDecl md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams);
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- if (md != null) injectMethod(tdParent, md);
+ recursiveSetGeneratedBy(md, annotationNode);
+ if (md != null) injectMethod(parent, md);
}
addObtainVia(bfd, fieldNode);
- builderFields.add(bfd);
- allFields.append(fieldNode);
+ job.builderFields.add(bfd);
}
- // Set the names of the builder classes.
- 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;
- if (extendsClause instanceof JCTypeApply) {
- // Remember the type arguments, because we need them for the extends clause of our abstract builder class.
- superclassTypeParams = ((JCTypeApply) extendsClause).getTypeArguments();
- // A class name with a generics type, e.g., "Superclass<A>".
- extendsClause = ((JCTypeApply) extendsClause).getType();
- }
- if (extendsClause instanceof JCFieldAccess) {
- Name superclassClassName = ((JCFieldAccess)extendsClause).getIdentifier();
- String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName);
- superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess) extendsClause,
- tdParent.toName(superclassBuilderClassName));
- } else if (extendsClause != null) {
- String superclassBuilderClassName = builderClassNameTemplate.replace("*", extendsClause.toString());
- superclassBuilderClassExpression = chainDots(tdParent, extendsClause.toString(), superclassBuilderClassName);
- }
- // If there is no superclass, superclassBuilderClassExpression is still == null at this point.
- // You can use it to check whether to inherit or not.
-
- typeParams = td.typarams;
+ job.typeParams = job.builderTypeParams = td.typarams;
+ job.builderClassName = job.replaceBuilderClassName(td.name);
+ if (!checkName("builderClassName", job.builderClassName, annotationNode)) return;
// <C, B> are the generics for our builder.
String classGenericName = "C";
@@ -214,14 +222,46 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// We have to make sure that the generics' names do not collide with any generics on the annotated class,
// the classname itself, or any member type name of the annotated class.
// For instance, if there are generics <B, B2, C> on the annotated class, use "C2" and "B3" for our builder.
- java.util.HashSet<String> usedNames = gatherUsedTypeNames(typeParams, td);
+ java.util.HashSet<String> usedNames = gatherUsedTypeNames(job.typeParams, td);
classGenericName = generateNonclashingNameFor(classGenericName, usedNames);
builderGenericName = generateNonclashingNameFor(builderGenericName, usedNames);
- thrownExceptions = List.nil();
+ JavacTreeMaker maker = annotationNode.getTreeMaker();
+
+ {
+ JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, parent, job.typeParams);
+ JCTypeParameter c = maker.TypeParameter(parent.toName(classGenericName), List.<JCExpression>of(annotatedClass));
+ ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.sourceNode);
+ typeParamsForBuilder.append(maker.Ident(parent.toName(classGenericName)));
+ typeParamsForBuilder.append(maker.Ident(parent.toName(builderGenericName)));
+ JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, parent, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList());
+ JCTypeParameter d = maker.TypeParameter(parent.toName(builderGenericName), List.<JCExpression>of(typeApply));
+ if (job.typeParams == null || job.typeParams.isEmpty()) {
+ job.builderTypeParams_ = List.of(c, d);
+ } else {
+ job.builderTypeParams_ = job.typeParams.append(c).append(d);
+ }
+ }
+
+ JCTree extendsClause = Javac.getExtendsClause(td);
+ JCExpression superclassBuilderClass = null;
+ if (extendsClause instanceof JCTypeApply) {
+ // Remember the type arguments, because we need them for the extends clause of our abstract builder class.
+ superclassTypeParams = ((JCTypeApply) extendsClause).getTypeArguments();
+ // A class name with a generics type, e.g., "Superclass<A>".
+ extendsClause = ((JCTypeApply) extendsClause).getType();
+ }
+ if (extendsClause instanceof JCFieldAccess) {
+ Name superclassName = ((JCFieldAccess) extendsClause).getIdentifier();
+ String superclassBuilderClassName = superclassName.toString() + "Builder";
+ superclassBuilderClass = parent.getTreeMaker().Select((JCFieldAccess) extendsClause, parent.toName(superclassBuilderClassName));
+ } else if (extendsClause != null) {
+ String superclassBuilderClassName = extendsClause.toString() + "Builder";
+ superclassBuilderClass = chainDots(parent, extendsClause.toString(), superclassBuilderClassName);
+ }
// Check validity of @ObtainVia fields, and add check if adding cleaning for @Singular is necessary.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
@@ -240,83 +280,85 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
}
+ job.builderAbstractClassName = job.builderClassName = job.replaceBuilderClassName(td.name);
+ job.builderImplClassName = job.builderAbstractClassName + "Impl";
+
// Create the abstract builder class.
- JavacNode builderType = findInnerClass(tdParent, builderClassName);
- if (builderType == null) {
- builderType = generateBuilderAbstractClass(annotationNode, tdParent, builderClassName, superclassBuilderClassExpression,
- typeParams, superclassTypeParams, classGenericName, builderGenericName);
- recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext());
+ job.builderAbstractType = findInnerClass(parent, job.builderClassName);
+ if (job.builderAbstractType == null) {
+ job.builderAbstractType = generateBuilderAbstractClass(job, superclassBuilderClass, superclassTypeParams, classGenericName, builderGenericName);
+ recursiveSetGeneratedBy(job.builderAbstractType.get(), annotationNode);
} else {
- JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get();
+ JCClassDecl builderTypeDeclaration = (JCClassDecl) job.builderAbstractType.get();
if (!builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)
|| !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.ABSTRACT)) {
annotationNode.addError("Existing Builder must be an abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderAbstractType, annotationNode);
// Generate errors for @Singular BFDs that have one already defined node.
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
SingularData sd = bfd.singularData;
if (sd == null) continue;
JavacSingularizer singularizer = sd.getSingularizer();
if (singularizer == null) continue;
- if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderAbstractType, sd)) {
bfd.singularData = null;
}
}
}
// Generate the fields in the abstract builder class that hold the values for the instance.
- generateBuilderFields(builderType, builderFields, ast);
+ job.setBuilderToAbstract();
+ generateBuilderFields(job.builderType, job.builderFields, annotationNode);
if (addCleaning) {
- JavacTreeMaker maker = builderType.getTreeMaker();
- JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null);
- recursiveSetGeneratedBy(uncleanField, ast, annotationNode.getContext());
- injectFieldAndMarkGenerated(builderType, uncleanField);
+ JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), job.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null);
+ recursiveSetGeneratedBy(uncleanField, annotationNode);
+ injectFieldAndMarkGenerated(job.builderType, uncleanField);
}
- if (toBuilder) {
+ if (job.toBuilder) {
// Generate $fillValuesFrom() method in the abstract builder.
- JCMethodDecl fvm = generateFillValuesMethod(tdParent, superclassBuilderClassExpression != null, builderGenericName, classGenericName, builderClassName);
- recursiveSetGeneratedBy(fvm, ast, annotationNode.getContext());
- injectMethod(builderType, fvm);
+ JCMethodDecl fvm = generateFillValuesMethod(job, superclassBuilderClass != null, builderGenericName, classGenericName);
+ recursiveSetGeneratedBy(fvm, annotationNode);
+ injectMethod(job.builderType, fvm);
// Generate $fillValuesFromInstanceIntoBuilder() method in the builder implementation class.
- JCMethodDecl sfvm = generateStaticFillValuesMethod(tdParent, builderClassName, typeParams, builderFields, superbuilderAnnotation.setterPrefix());
- recursiveSetGeneratedBy(sfvm, ast, annotationNode.getContext());
- injectMethod(builderType, sfvm);
+ JCMethodDecl sfvm = generateStaticFillValuesMethod(job, annInstance.setterPrefix());
+ recursiveSetGeneratedBy(sfvm, annotationNode);
+ injectMethod(job.builderType, sfvm);
}
// Generate abstract self() and build() methods in the abstract builder.
- JCMethodDecl asm = generateAbstractSelfMethod(cfv, tdParent, superclassBuilderClassExpression != null, builderGenericName);
- recursiveSetGeneratedBy(asm, ast, annotationNode.getContext());
- injectMethod(builderType, asm);
- JCMethodDecl abm = generateAbstractBuildMethod(cfv, tdParent, buildMethodName, builderFields, superclassBuilderClassExpression != null, classGenericName);
- recursiveSetGeneratedBy(abm, ast, annotationNode.getContext());
- injectMethod(builderType, abm);
+ JCMethodDecl asm = generateAbstractSelfMethod(job, superclassBuilderClass != null, builderGenericName);
+ recursiveSetGeneratedBy(asm, annotationNode);
+ injectMethod(job.builderType, asm);
+ JCMethodDecl abm = generateAbstractBuildMethod(job, superclassBuilderClass != null, classGenericName);
+ recursiveSetGeneratedBy(abm, annotationNode);
+ injectMethod(job.builderType, abm);
// Create the setter methods in the abstract builder.
- for (BuilderFieldData bfd : builderFields) {
- generateSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, builderGenericName, superbuilderAnnotation.setterPrefix());
+ for (BuilderFieldData bfd : job.builderFields) {
+ generateSetterMethodsForBuilder(job, bfd, builderGenericName, annInstance.setterPrefix());
}
// Create the toString() method for the abstract builder.
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
- for (BuilderFieldData bfd : builderFields) {
+ for (BuilderFieldData bfd : job.builderFields) {
for (JavacNode f : bfd.createdFields) {
fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false));
}
}
// Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder.
- JCMethodDecl toStringMethod = HandleToString.createToString(builderType, fieldNodes, true, superclassBuilderClassExpression != null, FieldAccess.ALWAYS_FIELD, ast);
- if (toStringMethod != null) injectMethod(builderType, toStringMethod);
+ JCMethodDecl toStringMethod = HandleToString.createToString(job.builderType, fieldNodes, true, superclassBuilderClass != null, FieldAccess.ALWAYS_FIELD, annotationNode);
+ if (toStringMethod != null) injectMethod(job.builderType, toStringMethod);
// If clean methods are requested, add them now.
if (addCleaning) {
- JCMethodDecl md = generateCleanMethod(builderFields, builderType, ast);
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- injectMethod(builderType, md);
+ JCMethodDecl md = generateCleanMethod(job.builderFields, job.builderType, annotationNode);
+ recursiveSetGeneratedBy(md, annotationNode);
+ injectMethod(job.builderType, md);
}
boolean isAbstract = (td.mods.flags & Flags.ABSTRACT) != 0;
@@ -324,69 +366,71 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// Only non-abstract classes get the Builder implementation.
// Create the builder implementation class.
- JavacNode builderImplType = findInnerClass(tdParent, builderImplClassName);
- if (builderImplType == null) {
- builderImplType = generateBuilderImplClass(annotationNode, tdParent, builderImplClassName, builderClassName, typeParams);
- recursiveSetGeneratedBy(builderImplType.get(), ast, annotationNode.getContext());
+ job.builderImplType = findInnerClass(parent, job.builderImplClassName);
+ if (job.builderImplType == null) {
+ job.builderImplType = generateBuilderImplClass(job);
+ recursiveSetGeneratedBy(job.builderImplType.get(), annotationNode);
} else {
- JCClassDecl builderImplTypeDeclaration = (JCClassDecl) builderImplType.get();
+ JCClassDecl builderImplTypeDeclaration = (JCClassDecl) job.builderImplType.get();
if (!builderImplTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)
|| builderImplTypeDeclaration.getModifiers().getFlags().contains(Modifier.ABSTRACT)) {
annotationNode.addError("Existing BuilderImpl must be a non-abstract static inner class.");
return;
}
- sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderImplType, annotationNode);
+ sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderImplType, annotationNode);
}
// Create a simple constructor for the BuilderImpl class.
- JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), builderImplType, List.<JavacNode>nil(), false, annotationNode);
- if (cd != null) injectMethod(builderImplType, cd);
+ JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.<JCAnnotation>nil(), job.builderImplType, List.<JavacNode>nil(), false, annotationNode);
+ if (cd != null) injectMethod(job.builderImplType, cd);
+ job.setBuilderToImpl();
// Create the self() and build() methods in the BuilderImpl.
- JCMethodDecl selfMethod = generateSelfMethod(cfv, builderImplType, typeParams);
- recursiveSetGeneratedBy(selfMethod, ast, annotationNode.getContext());
- injectMethod(builderImplType, selfMethod);
- if (methodExists(buildMethodName, builderImplType, -1) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl buildMethod = generateBuildMethod(cfv, buildMethodName, tdParent, builderImplType, builderFields, thrownExceptions);
- recursiveSetGeneratedBy(buildMethod, ast, annotationNode.getContext());
- injectMethod(builderImplType, buildMethod);
+ JCMethodDecl selfMethod = generateSelfMethod(job);
+ recursiveSetGeneratedBy(selfMethod, annotationNode);
+ injectMethod(job.builderType, selfMethod);
+ if (methodExists(job.buildMethodName, job.builderType, -1) == MemberExistsResult.NOT_EXISTS) {
+ JCMethodDecl buildMethod = generateBuildMethod(job, buildMethodThrownExceptions);
+ recursiveSetGeneratedBy(buildMethod, annotationNode);
+ injectMethod(job.builderType, buildMethod);
}
}
// Generate a constructor in the annotated class that takes a builder as argument.
- if (!constructorExists(tdParent, builderClassName)) {
- generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
- superclassBuilderClassExpression != null);
+ if (!constructorExists(job.parentType, job.builderAbstractClassName)) {
+ job.setBuilderToAbstract();
+ generateBuilderBasedConstructor(job, superclassBuilderClass != null);
}
- if (isAbstract) {
+ if (!isAbstract) {
// Only non-abstract classes get the builder() and toBuilder() methods.
- return;
- }
- // Add the builder() method to the annotated class.
- // Allow users to specify their own builder() methods, e.g., to provide default values.
- if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
- if (generateBuilderMethod) {
- JCMethodDecl builderMethod = generateBuilderMethod(cfv, builderMethodName, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
- recursiveSetGeneratedBy(builderMethod, ast, annotationNode.getContext());
- if (builderMethod != null) injectMethod(tdParent, builderMethod);
- }
-
- // Add the toBuilder() method to the annotated class.
- if (toBuilder) {
- switch (methodExists(TO_BUILDER_METHOD_NAME, tdParent, 0)) {
- case EXISTS_BY_USER:
- break;
- case NOT_EXISTS:
- JCMethodDecl md = generateToBuilderMethod(cfv, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
- if (md != null) {
- recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
- injectMethod(tdParent, md);
+ // Add the builder() method to the annotated class.
+ // Allow users to specify their own builder() methods, e.g., to provide default values.
+ if (generateBuilderMethod && methodExists(job.builderMethodName, job.parentType, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false;
+ if (generateBuilderMethod) {
+ JCMethodDecl builderMethod = generateBuilderMethod(job);
+ if (builderMethod != null) {
+ recursiveSetGeneratedBy(builderMethod, annotationNode);
+ injectMethod(job.parentType, builderMethod);
+ }
+ }
+
+ // Add the toBuilder() method to the annotated class.
+ if (job.toBuilder) {
+ switch (methodExists(TO_BUILDER_METHOD_NAME, job.parentType, 0)) {
+ case EXISTS_BY_USER:
+ break;
+ case NOT_EXISTS:
+ JCMethodDecl md = generateToBuilderMethod(job);
+ if (md != null) {
+ recursiveSetGeneratedBy(md, annotationNode);
+ injectMethod(job.parentType, md);
+ }
+ break;
+ default:
+ // Should not happen.
}
- break;
- default:
- // Should not happen.
}
}
@@ -400,163 +444,150 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
/**
* Creates and returns the abstract builder class and injects it into the annotated class.
*/
- private JavacNode generateBuilderAbstractClass(JavacNode source, JavacNode tdParent, String builderClass,
- JCExpression superclassBuilderClassExpression, List<JCTypeParameter> typeParams,
- List<JCExpression> superclassTypeParams, String classGenericName, String builderGenericName) {
-
- JavacTreeMaker maker = tdParent.getTreeMaker();
+ private JavacNode generateBuilderAbstractClass(SuperBuilderJob job, JCExpression superclassBuilderClass, List<JCExpression> superclassTypeParams, String classGenericName, String builderGenericName) {
+ JavacTreeMaker maker = job.parentType.getTreeMaker();
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.ABSTRACT | Flags.PUBLIC);
// Keep any type params of the annotated class.
ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>();
- allTypeParams.addAll(copyTypeParams(source, typeParams));
+ allTypeParams.appendList(copyTypeParams(job.sourceNode, job.typeParams));
// Add builder-specific type params required for inheritable builders.
// 1. The return type for the build() method, named "C", which extends the annotated class.
- JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams);
+ JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, job.parentType, job.typeParams);
- allTypeParams.add(maker.TypeParameter(tdParent.toName(classGenericName), List.<JCExpression>of(annotatedClass)));
+ allTypeParams.append(maker.TypeParameter(job.toName(classGenericName), List.<JCExpression>of(annotatedClass)));
// 2. The return type for all setter methods, named "B", which extends this builder class.
- Name builderClassName = tdParent.toName(builderClass);
- ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(typeParams, maker, source.getContext());
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName)));
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName)));
- JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, tdParent, builderClassName, false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList());
- allTypeParams.add(maker.TypeParameter(tdParent.toName(builderGenericName), List.<JCExpression>of(typeApply)));
+ Name builderClassName = job.toName(job.builderClassName);
+ ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.sourceNode);
+ typeParamsForBuilder.append(maker.Ident(job.toName(classGenericName)));
+ typeParamsForBuilder.append(maker.Ident(job.toName(builderGenericName)));
+ JCTypeApply typeApply = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, builderClassName, false, List.<JCTypeParameter>nil()), typeParamsForBuilder.toList());
+ allTypeParams.append(maker.TypeParameter(job.toName(builderGenericName), List.<JCExpression>of(typeApply)));
JCExpression extending = null;
- if (superclassBuilderClassExpression != null) {
+ if (superclassBuilderClass != null) {
// If the annotated class extends another class, we want this builder to extend the builder of the superclass.
// 1. Add the type parameters of the superclass.
- typeParamsForBuilder = getTypeParamExpressions(superclassTypeParams, maker, source.getContext());
+ typeParamsForBuilder = getTypeParamExpressions(superclassTypeParams, maker, job.sourceNode);
// 2. Add the builder type params <C, B>.
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(classGenericName)));
- typeParamsForBuilder.add(maker.Ident(tdParent.toName(builderGenericName)));
- extending = maker.TypeApply(superclassBuilderClassExpression, typeParamsForBuilder.toList());
+ typeParamsForBuilder.append(maker.Ident(job.toName(classGenericName)));
+ typeParamsForBuilder.append(maker.Ident(job.toName(builderGenericName)));
+ extending = maker.TypeApply(superclassBuilderClass, typeParamsForBuilder.toList());
}
JCClassDecl builder = maker.ClassDef(mods, builderClassName, allTypeParams.toList(), extending, List.<JCExpression>nil(), List.<JCTree>nil());
- return injectType(tdParent, builder);
+ recursiveSetGeneratedBy(builder, job.sourceNode);
+ return injectType(job.parentType, builder);
}
/**
* Creates and returns the concrete builder implementation class and injects it into the annotated class.
*/
- private JavacNode generateBuilderImplClass(JavacNode source, JavacNode tdParent, String builderImplClass, String builderAbstractClass, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = tdParent.getTreeMaker();
+ private JavacNode generateBuilderImplClass(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
JCModifiers mods = maker.Modifiers(Flags.STATIC | Flags.PRIVATE | Flags.FINAL);
// Extend the abstract builder.
- JCExpression extending = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderAbstractClass), false, List.<JCTypeParameter>nil());
- // Add any type params of the annotated class.
- ListBuffer<JCTypeParameter> allTypeParams = new ListBuffer<JCTypeParameter>();
- allTypeParams.addAll(copyTypeParams(source, typeParams));
+ JCExpression extending = namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil());
+
// Add builder-specific type params required for inheritable builders.
// 1. The return type for the build() method (named "C" in the abstract builder), which is the annotated class.
- JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, tdParent, typeParams);
+ JCExpression annotatedClass = namePlusTypeParamsToTypeReference(maker, job.parentType, job.typeParams);
// 2. The return type for all setter methods (named "B" in the abstract builder), which is this builder class.
- JCExpression builderImplClassExpression = namePlusTypeParamsToTypeReference(maker, tdParent, tdParent.toName(builderImplClass), false, typeParams);
+ JCExpression builderImplClassExpression = namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams);
- ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(typeParams, maker, source.getContext());
- typeParamsForBuilder.add(annotatedClass);
- typeParamsForBuilder.add(builderImplClassExpression);
+ ListBuffer<JCExpression> typeParamsForBuilder = getTypeParamExpressions(job.typeParams, maker, job.sourceNode);
+ typeParamsForBuilder.append(annotatedClass);
+ typeParamsForBuilder.append(builderImplClassExpression);
extending = maker.TypeApply(extending, typeParamsForBuilder.toList());
- JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderImplClass), copyTypeParams(source, typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil());
- return injectType(tdParent, builder);
+ JCClassDecl builder = maker.ClassDef(mods, job.toName(job.builderImplClassName), copyTypeParams(job.parentType, job.typeParams), extending, List.<JCExpression>nil(), List.<JCTree>nil());
+ recursiveSetGeneratedBy(builder, job.sourceNode);
+ return injectType(job.parentType, builder);
}
/**
* Generates a constructor that has a builder as the only parameter.
* The values from the builder are used to initialize the fields of new instances.
*
- * @param typeNode
- * the type (with the {@code @Builder} annotation) for which a
- * constructor should be generated.
- * @param typeParams
- * @param builderFields a list of fields in the builder which should be assigned to new instances.
- * @param source the annotation (used for setting source code locations for the generated code).
* @param callBuilderBasedSuperConstructor
* If {@code true}, the constructor will explicitly call a super
* constructor with the builder as argument. Requires
* {@code builderClassAsParameter != null}.
*/
- private void generateBuilderBasedConstructor(CheckerFrameworkVersion cfv, JavacNode typeNode, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, JavacNode source, String builderClassName, boolean callBuilderBasedSuperConstructor) {
- JavacTreeMaker maker = typeNode.getTreeMaker();
+ private void generateBuilderBasedConstructor(SuperBuilderJob job, boolean callBuilderBasedSuperConstructor) {
+ JavacTreeMaker maker = job.getTreeMaker();
AccessLevel level = AccessLevel.PROTECTED;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- Name builderVariableName = typeNode.toName(BUILDER_VARIABLE_NAME);
- for (BuilderFieldData bfd : builderFields) {
+ Name builderVariableName = job.toName(BUILDER_VARIABLE_NAME);
+ for (BuilderFieldData bfd : job.builderFields) {
JCExpression rhs;
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.builderFieldName, "b");
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, job.sourceNode, statements, bfd.builderFieldName, "b");
rhs = maker.Ident(bfd.singularData.getPluralName());
} else {
rhs = maker.Select(maker.Ident(builderVariableName), bfd.builderFieldName);
}
- JCFieldAccess fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName);
+ JCFieldAccess fieldInThis = maker.Select(maker.Ident(job.toName("this")), bfd.rawName);
JCStatement assign = maker.Exec(maker.Assign(fieldInThis, rhs));
// In case of @Builder.Default, set the value to the default if it was not set in the builder.
if (bfd.nameOfSetFlag != null) {
JCFieldAccess setField = maker.Select(maker.Ident(builderVariableName), bfd.nameOfSetFlag);
- fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName);
- JCExpression parentTypeRef = namePlusTypeParamsToTypeReference(maker, typeNode, List.<JCTypeParameter>nil());
- JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) typeNode.get()).typarams), maker.Select(parentTypeRef, bfd.nameOfDefaultProvider), List.<JCExpression>nil()));
+ fieldInThis = maker.Select(maker.Ident(job.toName("this")), bfd.rawName);
+ JCExpression parentTypeRef = namePlusTypeParamsToTypeReference(maker, job.parentType, List.<JCTypeParameter>nil());
+ JCAssign assignDefault = maker.Assign(fieldInThis, maker.Apply(typeParameterNames(maker, ((JCClassDecl) job.parentType.get()).typarams), maker.Select(parentTypeRef, bfd.nameOfDefaultProvider), List.<JCExpression>nil()));
statements.append(maker.If(setField, assign, maker.Exec(assignDefault)));
} else {
statements.append(assign);
}
if (hasNonNullAnnotations(bfd.originalFieldNode)) {
- JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, source);
+ JCStatement nullCheck = generateNullCheck(maker, bfd.originalFieldNode, job.sourceNode);
if (nullCheck != null) statements.append(nullCheck);
}
}
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
JCModifiers mods = maker.Modifiers(toJavacModifier(level), annsOnMethod);
// Create a constructor that has just the builder as parameter.
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
- long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
- Name builderClassname = typeNode.toName(builderClassName);
+ long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, job.getContext());
// First add all generics that are present on the parent type.
- ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker, typeNode.getContext());
+ ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(job.typeParams, maker, job.sourceNode);
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
- typeParamsForBuilderParameter.add(wildcard);
+ typeParamsForBuilderParameter.append(wildcard);
wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
- typeParamsForBuilderParameter.add(wildcard);
- JCTypeApply paramType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, typeNode, builderClassname, false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
+ typeParamsForBuilderParameter.append(wildcard);
+ JCTypeApply paramType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), builderVariableName, paramType, null);
params.append(param);
if (callBuilderBasedSuperConstructor) {
// The first statement must be the call to the super constructor.
JCMethodInvocation callToSuperConstructor = maker.Apply(List.<JCExpression>nil(),
- maker.Ident(typeNode.toName("super")),
+ maker.Ident(job.toName("super")),
List.<JCExpression>of(maker.Ident(builderVariableName)));
statements.prepend(maker.Exec(callToSuperConstructor));
}
- JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
+ JCMethodDecl constr = recursiveSetGeneratedBy(maker.MethodDef(mods, job.toName("<init>"),
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
- maker.Block(0L, statements.toList()), null), source.get(), typeNode.getContext());
+ maker.Block(0L, statements.toList()), null), job.sourceNode);
- injectMethod(typeNode, constr, null, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
+ injectMethod(job.parentType, constr, null, Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID));
}
- private JCMethodDecl generateBuilderMethod(CheckerFrameworkVersion cfv, String builderMethodName, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = type.getTreeMaker();
-
- ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name));
+ private JCMethodDecl generateBuilderMethod(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
- JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, typeParams), List.<JCExpression>nil(), null);
+ JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams), List.<JCExpression>nil(), null);
JCStatement statement = maker.Return(call);
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
@@ -565,16 +596,19 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// Add any type params of the annotated class to the return type.
ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>();
- typeParameterNames.addAll(typeParameterNames(maker, typeParams));
+ typeParameterNames.appendList(typeParameterNames(maker, job.typeParams));
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
- typeParameterNames.add(wildcard);
- typeParameterNames.add(wildcard);
- JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList());
-
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(builderMethodName), returnType, copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ typeParameterNames.append(wildcard);
+ typeParameterNames.append(wildcard);
+ // And return type annotations.
+ List<JCAnnotation> annsOnParamType = List.nil();
+ if (job.checkerFramework.generateUnique()) annsOnParamType = List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil()));
+ JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil(), annsOnParamType), typeParameterNames.toList());
+
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(job.builderMethodName), returnType, copyTypeParams(job.sourceNode, job.typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
@@ -586,15 +620,12 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* }
* </pre>
*/
- private JCMethodDecl generateToBuilderMethod(CheckerFrameworkVersion cfv, String builderClassName, String builderImplClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateToBuilderMethod(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
- ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
- for (JCTypeParameter typeParam : typeParams) typeArgs.append(maker.Ident(typeParam.name));
-
- JCExpression newClass = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, typeParams), List.<JCExpression>nil(), null);
- List<JCExpression> methodArgs = List.<JCExpression>of(maker.Ident(type.toName("this")));
- JCMethodInvocation invokeFillMethod = maker.Apply(List.<JCExpression>nil(), maker.Select(newClass, type.toName(FILL_VALUES_METHOD_NAME)), methodArgs);
+ JCExpression newClass = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderImplClassName), false, job.typeParams), List.<JCExpression>nil(), null);
+ List<JCExpression> methodArgs = List.<JCExpression>of(maker.Ident(job.toName("this")));
+ JCMethodInvocation invokeFillMethod = maker.Apply(List.<JCExpression>nil(), maker.Select(newClass, job.toName(FILL_VALUES_METHOD_NAME)), methodArgs);
JCStatement statement = maker.Return(invokeFillMethod);
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
@@ -602,16 +633,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
// Add any type params of the annotated class to the return type.
ListBuffer<JCExpression> typeParameterNames = new ListBuffer<JCExpression>();
- typeParameterNames.addAll(typeParameterNames(maker, typeParams));
+ typeParameterNames.appendList(typeParameterNames(maker, job.typeParams));
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
- typeParameterNames.add(wildcard);
- typeParameterNames.add(wildcard);
- JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList());
+ typeParameterNames.append(wildcard);
+ typeParameterNames.append(wildcard);
+ JCTypeApply returnType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.toName(job.builderAbstractClassName), false, List.<JCTypeParameter>nil()), typeParameterNames.toList());
- List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
- JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), type.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ List<JCAnnotation> annsOnMethod = job.checkerFramework.generateSideEffectFree() ? List.of(maker.Annotation(genTypeRef(job.parentType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil())) : List.<JCAnnotation>nil();
+ JCMethodDecl methodDef = maker.MethodDef(maker.Modifiers(modifiers, annsOnMethod), job.toName(TO_BUILDER_METHOD_NAME), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ createRelevantNonNullAnnotation(job.parentType, methodDef);
return methodDef;
}
@@ -621,43 +652,43 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* <pre>
* protected B $fillValuesFrom(final C instance) {
* super.$fillValuesFrom(instance);
- * FoobarBuilderImpl.$fillValuesFromInstanceIntoBuilder(instance, this);
+ * FoobarBuilder.$fillValuesFromInstanceIntoBuilder(instance, this);
* return self();
* }
* </pre>
*/
- private JCMethodDecl generateFillValuesMethod(JavacNode type, boolean inherited, String builderGenericName, String classGenericName, String builderImplClassName) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateFillValuesMethod(SuperBuilderJob job, boolean inherited, String builderGenericName, String classGenericName) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
if (inherited) {
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil());
annotations = List.of(overrideAnnotation);
}
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, annotations);
- Name name = type.toName(FILL_VALUES_METHOD_NAME);
- JCExpression returnType = maker.Ident(type.toName(builderGenericName));
+ Name name = job.toName(FILL_VALUES_METHOD_NAME);
+ JCExpression returnType = maker.Ident(job.toName(builderGenericName));
- JCExpression classGenericNameExpr = maker.Ident(type.toName(classGenericName));
- JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(INSTANCE_VARIABLE_NAME), classGenericNameExpr, null);
+ JCExpression classGenericNameExpr = maker.Ident(job.toName(classGenericName));
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), classGenericNameExpr, null);
ListBuffer<JCStatement> body = new ListBuffer<JCStatement>();
if (inherited) {
// Call super.
JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
- maker.Select(maker.Ident(type.toName("super")), name),
- List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME))));
+ maker.Select(maker.Ident(job.toName("super")), name),
+ List.<JCExpression>of(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME))));
body.append(maker.Exec(callToSuper));
}
// Call the builder implemention's helper method that actually fills the values from the instance.
- JCExpression ref = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderImplClassName), false, List.<JCTypeParameter>nil());
+ JCExpression ref = namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil());
JCMethodInvocation callStaticFillValuesMethod = maker.Apply(List.<JCExpression>nil(),
- maker.Select(ref, type.toName(STATIC_FILL_VALUES_METHOD_NAME)),
- List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME)), maker.Ident(type.toName("this"))));
+ maker.Select(ref, job.toName(STATIC_FILL_VALUES_METHOD_NAME)),
+ List.<JCExpression>of(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME)), maker.Ident(job.toName("this"))));
body.append(maker.Exec(callStaticFillValuesMethod));
- JCReturn returnStatement = maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName(SELF_METHOD)), List.<JCExpression>nil()));
+ JCReturn returnStatement = maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(SELF_METHOD)), List.<JCExpression>nil()));
body.append(returnStatement);
JCBlock bodyBlock = maker.Block(0, body.toList());
@@ -674,58 +705,58 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
* b.field(instance.field);
* }
* </pre>
- * @param setterPrefix the prefix for setter methods
*/
- private JCMethodDecl generateStaticFillValuesMethod(JavacNode type, String builderClassname, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, String setterPrefix) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateStaticFillValuesMethod(SuperBuilderJob job, String setterPrefix) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
JCModifiers modifiers = maker.Modifiers(Flags.PRIVATE | Flags.STATIC, annotations);
- Name name = type.toName(STATIC_FILL_VALUES_METHOD_NAME);
+ Name name = job.toName(STATIC_FILL_VALUES_METHOD_NAME);
JCExpression returnType = maker.TypeIdent(CTC_VOID);
// 1st parameter: "Foobar instance"
- JCVariableDecl paramInstance = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(INSTANCE_VARIABLE_NAME), cloneSelfType(type), null);
+ JCVariableDecl paramInstance = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), cloneSelfType(job.parentType), null);
// 2nd parameter: "FoobarBuilder<?, ?> b" (plus generics on the annotated type)
// First add all generics that are present on the parent type.
- ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(typeParams, maker, type.getContext());
+ ListBuffer<JCExpression> typeParamsForBuilderParameter = getTypeParamExpressions(job.typeParams, maker, job.sourceNode);
// Now add the <?, ?>.
JCWildcard wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
- typeParamsForBuilderParameter.add(wildcard);
+ typeParamsForBuilderParameter.append(wildcard);
wildcard = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
- typeParamsForBuilderParameter.add(wildcard);
- JCTypeApply builderType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassname), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
- JCVariableDecl paramBuilder = maker.VarDef(maker.Modifiers(Flags.LocalVarFlags), type.toName(BUILDER_VARIABLE_NAME), builderType, null);
-
+ typeParamsForBuilderParameter.append(wildcard);
+ JCTypeApply builderType = maker.TypeApply(namePlusTypeParamsToTypeReference(maker, job.parentType, job.getBuilderClassName(), false, List.<JCTypeParameter>nil()), typeParamsForBuilderParameter.toList());
+ JCVariableDecl paramBuilder = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(BUILDER_VARIABLE_NAME), builderType, null);
+
ListBuffer<JCStatement> body = new ListBuffer<JCStatement>();
// Call the builder's setter methods to fill the values from the instance.
- for (BuilderFieldData bfd : builderFields) {
- JCExpressionStatement exec = createSetterCallWithInstanceValue(bfd, type, maker, setterPrefix);
+ for (BuilderFieldData bfd : job.builderFields) {
+ JCExpressionStatement exec = createSetterCallWithInstanceValue(bfd, job, setterPrefix);
body.append(exec);
}
JCBlock bodyBlock = maker.Block(0, body.toList());
-
- return maker.MethodDef(modifiers, name, returnType, copyTypeParams(type, typeParams), List.of(paramInstance, paramBuilder), List.<JCExpression>nil(), bodyBlock, null);
+
+ return maker.MethodDef(modifiers, name, returnType, copyTypeParams(job.builderType, job.typeParams), List.of(paramInstance, paramBuilder), List.<JCExpression>nil(), bodyBlock, null);
}
- private JCExpressionStatement createSetterCallWithInstanceValue(BuilderFieldData bfd, JavacNode type, JavacTreeMaker maker, String setterPrefix) {
+ private JCExpressionStatement createSetterCallWithInstanceValue(BuilderFieldData bfd, SuperBuilderJob job, String setterPrefix) {
+ JavacTreeMaker maker = job.getTreeMaker();
JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2];
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
for (int i = 0; i < tgt.length; i++) {
- tgt[i] = maker.Select(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME)), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field()));
+ tgt[i] = maker.Select(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME)), bfd.obtainVia == null ? bfd.rawName : job.toName(bfd.obtainVia.field()));
}
} else {
if (bfd.obtainVia.isStatic()) {
for (int i = 0; i < tgt.length; i++) {
- JCExpression typeRef = namePlusTypeParamsToTypeReference(maker, type, List.<JCTypeParameter>nil());
- JCExpression c = maker.Select(typeRef, type.toName(bfd.obtainVia.method()));
- tgt[i] = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>of(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME))));
+ JCExpression typeRef = namePlusTypeParamsToTypeReference(maker, job.parentType, List.<JCTypeParameter>nil());
+ JCExpression c = maker.Select(typeRef, job.toName(bfd.obtainVia.method()));
+ tgt[i] = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>of(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME))));
}
} else {
for (int i = 0; i < tgt.length; i++) {
- JCExpression c = maker.Select(maker.Ident(type.toName(INSTANCE_VARIABLE_NAME)), type.toName(bfd.obtainVia.method()));
+ JCExpression c = maker.Select(maker.Ident(job.toName(INSTANCE_VARIABLE_NAME)), job.toName(bfd.obtainVia.method()));
tgt[i] = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil());
}
}
@@ -736,95 +767,105 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
arg = tgt[0];
} else {
JCExpression eqNull = maker.Binary(CTC_EQUAL, tgt[0], maker.Literal(CTC_BOT, null));
- String emptyMaker = bfd.singularData.getSingularizer().getEmptyMaker(bfd.singularData.getTargetFqn());
- JCExpression emptyCollection = maker.Apply(List.<JCExpression>nil(), chainDots(type, emptyMaker.split("\\.")), List.<JCExpression>nil());
+ JCExpression emptyCollection = bfd.singularData.getSingularizer().getEmptyExpression(bfd.singularData.getTargetFqn(), maker, bfd.singularData, job.parentType, job.sourceNode);
arg = maker.Conditional(eqNull, emptyCollection, tgt[1]);
}
String setterName = HandlerUtil.buildAccessorName(setterPrefix, bfd.name.toString());
- JCMethodInvocation apply = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(type.toName(BUILDER_VARIABLE_NAME)), type.toName(setterName)), List.of(arg));
+ JCMethodInvocation apply = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(job.toName(BUILDER_VARIABLE_NAME)), job.toName(setterName)), List.of(arg));
JCExpressionStatement exec = maker.Exec(apply);
return exec;
}
- private JCMethodDecl generateAbstractSelfMethod(CheckerFrameworkVersion cfv, JavacNode type, boolean override, String builderGenericName) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateAbstractSelfMethod(SuperBuilderJob job, boolean override, String builderGenericName) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
- JCAnnotation overrideAnnotation = override ? maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil()) : null;
- JCAnnotation rrAnnotation = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
- JCAnnotation sefAnnotation = cfv.generatePure() ? maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null;
+ JCAnnotation overrideAnnotation = override ? maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil()) : null;
+ JCAnnotation rrAnnotation = job.checkerFramework.generateReturnsReceiver() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
+ JCAnnotation sefAnnotation = job.checkerFramework.generatePure() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null;
if (sefAnnotation != null) annotations = annotations.prepend(sefAnnotation);
if (rrAnnotation != null) annotations = annotations.prepend(rrAnnotation);
if (overrideAnnotation != null) annotations = annotations.prepend(overrideAnnotation);
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED | Flags.ABSTRACT, annotations);
- Name name = type.toName(SELF_METHOD);
- JCExpression returnType = maker.Ident(type.toName(builderGenericName));
+ Name name = job.toName(SELF_METHOD);
+ JCExpression returnType = maker.Ident(job.toName(builderGenericName));
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
}
- private JCMethodDecl generateSelfMethod(CheckerFrameworkVersion cfv, JavacNode builderImplType, List<JCTypeParameter> typeParams) {
- JavacTreeMaker maker = builderImplType.getTreeMaker();
+ private JCMethodDecl generateSelfMethod(SuperBuilderJob job) {
+ JavacTreeMaker maker = job.getTreeMaker();
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(builderImplType, "Override"), List.<JCExpression>nil());
- JCAnnotation rrAnnotation = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
- JCAnnotation sefAnnotation = cfv.generatePure() ? maker.Annotation(genTypeRef(builderImplType, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null;
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil());
+ JCAnnotation rrAnnotation = job.checkerFramework.generateReturnsReceiver() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
+ JCAnnotation sefAnnotation = job.checkerFramework.generatePure() ? maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()) : null;
List<JCAnnotation> annsOnMethod = List.nil();
if (sefAnnotation != null) annsOnMethod = annsOnMethod.prepend(sefAnnotation);
if (rrAnnotation != null) annsOnMethod = annsOnMethod.prepend(rrAnnotation);
annsOnMethod = annsOnMethod.prepend(overrideAnnotation);
JCModifiers modifiers = maker.Modifiers(Flags.PROTECTED, annsOnMethod);
- Name name = builderImplType.toName(SELF_METHOD);
+ Name name = job.toName(SELF_METHOD);
- JCExpression returnType = namePlusTypeParamsToTypeReference(maker, builderImplType.up(), builderImplType.toName(builderImplType.getName()), false, typeParams);
- JCStatement statement = maker.Return(maker.Ident(builderImplType.toName("this")));
+ JCExpression returnType = namePlusTypeParamsToTypeReference(maker, job.builderType.up(), job.getBuilderClassName(), false, job.typeParams);
+ JCStatement statement = maker.Return(maker.Ident(job.toName("this")));
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
- private JCMethodDecl generateAbstractBuildMethod(CheckerFrameworkVersion cfv, JavacNode type, String methodName, java.util.List<BuilderFieldData> builderFields, boolean override, String classGenericName) {
- JavacTreeMaker maker = type.getTreeMaker();
+ private JCMethodDecl generateAbstractBuildMethod(SuperBuilderJob job, boolean override, String classGenericName) {
+ JavacTreeMaker maker = job.getTreeMaker();
List<JCAnnotation> annotations = List.nil();
if (override) {
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil());
annotations = List.of(overrideAnnotation);
}
- if (cfv.generateSideEffectFree()) annotations = annotations.prepend(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ if (job.checkerFramework.generateSideEffectFree()) annotations = annotations.prepend(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC | Flags.ABSTRACT, annotations);
- Name name = type.toName(methodName);
- JCExpression returnType = maker.Ident(type.toName(classGenericName));
+ Name name = job.toName(job.buildMethodName);
+ JCExpression returnType = maker.Ident(job.toName(classGenericName));
- List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields);
- return maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), null, null);
+ JCVariableDecl recv = HandleBuilder.generateReceiver(job);
+ JCMethodDecl methodDef;
+ if (recv != null && maker.hasMethodDefWithRecvParam()) {
+ methodDef = maker.MethodDefWithRecvParam(modifiers, name, returnType, List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
+ } else {
+ methodDef = maker.MethodDef(modifiers, name, returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
+ }
+ return methodDef;
}
-
- private JCMethodDecl generateBuildMethod(CheckerFrameworkVersion cfv, String buildName, JavacNode returnType, JavacNode type, java.util.List<BuilderFieldData> builderFields, List<JCExpression> thrownExceptions) {
- JavacTreeMaker maker = type.getTreeMaker();
+
+ private JCMethodDecl generateBuildMethod(SuperBuilderJob job, List<JCExpression> thrownExceptions) {
+ JavacTreeMaker maker = job.getTreeMaker();
JCExpression call;
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
// Use a constructor that only has this builder as parameter.
- List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(type.toName("this")));
- call = maker.NewClass(null, List.<JCExpression>nil(), cloneSelfType(returnType), builderArg, null);
+ List<JCExpression> builderArg = List.<JCExpression>of(maker.Ident(job.toName("this")));
+ call = maker.NewClass(null, List.<JCExpression>nil(), cloneSelfType(job.parentType), builderArg, null);
statements.append(maker.Return(call));
JCBlock body = maker.Block(0, statements.toList());
- JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(type, "Override"), List.<JCExpression>nil());
+ JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(job.builderType, "Override"), List.<JCExpression>nil());
List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
- if (cfv.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
+ if (job.checkerFramework.generateSideEffectFree()) annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
JCModifiers modifiers = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
- List<JCVariableDecl> params = HandleBuilder.generateBuildArgs(cfv, type, builderFields);
- JCMethodDecl methodDef = maker.MethodDef(modifiers, type.toName(buildName), cloneSelfType(returnType), List.<JCTypeParameter>nil(), params, thrownExceptions, body, null);
- createRelevantNonNullAnnotation(type, methodDef);
+ JCVariableDecl recv = HandleBuilder.generateReceiver(job);
+ JCMethodDecl methodDef;
+ if (recv != null && maker.hasMethodDefWithRecvParam()) {
+ methodDef = maker.MethodDefWithRecvParam(modifiers, job.toName(job.buildMethodName), cloneSelfType(job.parentType), List.<JCTypeParameter>nil(), recv, List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ } else {
+ methodDef = maker.MethodDef(modifiers, job.toName(job.buildMethodName), cloneSelfType(job.parentType), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ }
+ createRelevantNonNullAnnotation(job.builderType, methodDef);
return methodDef;
}
- private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
+ private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JavacNode source) {
JavacTreeMaker maker = type.getTreeMaker();
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
@@ -839,7 +880,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
- private void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) {
+ private void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JavacNode source) {
int len = builderFields.size();
java.util.List<JavacNode> existing = new ArrayList<JavacNode>();
for (JavacNode child : builderType.down()) {
@@ -851,7 +892,11 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
for (int i = len - 1; i >= 0; i--) {
BuilderFieldData bfd = builderFields.get(i);
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
- bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
+ java.util.List<JavacNode> fields = bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source);
+ for (JavacNode field : fields) {
+ generated.add((JCVariableDecl) field.get());
+ }
+ bfd.createdFields.addAll(fields);
} else {
JavacNode field = null, setFlag = null;
for (JavacNode exists : existing) {
@@ -862,7 +907,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
JavacTreeMaker maker = builderType.getTreeMaker();
if (field == null) {
JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
- JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, source, builderType.getContext()), null);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, source), null);
field = injectFieldAndMarkGenerated(builderType, newField);
generated.add(newField);
}
@@ -875,32 +920,33 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
bfd.createdFields.add(field);
}
}
- for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source, builderType.getContext());
+ for (JCVariableDecl gen : generated) recursiveSetGeneratedBy(gen, source);
}
- private void generateSetterMethodsForBuilder(CheckerFrameworkVersion cfv, final JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, final String builderGenericName, String setterPrefix) {
+ private void generateSetterMethodsForBuilder(final SuperBuilderJob job, BuilderFieldData fieldNode, final String builderGenericName, String setterPrefix) {
boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
- final JavacTreeMaker maker = builderType.getTreeMaker();
+ final JavacTreeMaker maker = job.getTreeMaker();
ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() {
- return maker.Ident(builderType.toName(builderGenericName));
+ return maker.Ident(job.toName(builderGenericName));
}};
StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() {
- return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(builderType.toName(SELF_METHOD)), List.<JCExpression>nil()));
+ return maker.Return(maker.Apply(List.<JCExpression>nil(), maker.Ident(job.toName(SELF_METHOD)), List.<JCExpression>nil()));
}};
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- generateSimpleSetterMethodForBuilder(cfv, builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode, setterPrefix);
+ generateSimpleSetterMethodForBuilder(job, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode, setterPrefix);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(cfv, fieldNode.singularData, deprecate, builderType, source.get(), true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
+ fieldNode.singularData.getSingularizer().generateMethods(job.checkerFramework, fieldNode.singularData, deprecate, job.builderType,
+ job.sourceNode, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC);
}
}
- private void generateSimpleSetterMethodForBuilder(CheckerFrameworkVersion cfv, JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, String setterPrefix) {
+ private void generateSimpleSetterMethodForBuilder(SuperBuilderJob job, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, String setterPrefix) {
String setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString());
- Name setterName_ = builderType.toName(setterName);
+ Name setterName_ = job.builderType.toName(setterName);
- for (JavacNode child : builderType.down()) {
+ for (JavacNode child : job.builderType.down()) {
if (child.getKind() != Kind.METHOD) continue;
JCMethodDecl methodDecl = (JCMethodDecl) child.get();
Name existingName = methodDecl.name;
@@ -910,23 +956,24 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
JavacTreeMaker maker = fieldNode.getTreeMaker();
List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode);
- JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, source, methodAnns, annosOnParam);
- if (cfv.generateCalledMethods()) {
- JCAnnotation ncAnno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(newMethod.getName().toString())));
- JCClassDecl builderTypeNode = (JCClassDecl) builderType.get();
- JCExpression selfType = namePlusTypeParamsToTypeReference(maker, builderType, builderTypeNode.typarams);
- JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>of(ncAnno)), builderType.toName("this"), selfType, null);
- newMethod.params = List.of(recv, newMethod.params.get(0));
+ JCMethodDecl newMethod = null;
+ if (job.checkerFramework.generateCalledMethods() && maker.hasMethodDefWithRecvParam()) {
+ JCAnnotation ncAnno = maker.Annotation(genTypeRef(job.sourceNode, CheckerFrameworkVersion.NAME__NOT_CALLED), List.<JCExpression>of(maker.Literal(setterName.toString())));
+ JCClassDecl builderTypeNode = (JCClassDecl) job.builderType.get();
+ JCExpression selfType = namePlusTypeParamsToTypeReference(maker, job.builderType, builderTypeNode.typarams, List.<JCAnnotation>of(ncAnno));
+ JCVariableDecl recv = maker.VarDef(maker.Modifiers(0L, List.<JCAnnotation>nil()), job.toName("this"), selfType, null);
+ newMethod = HandleSetter.createSetterWithRecv(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam, recv);
}
- if (cfv.generateReturnsReceiver()) {
+ if (newMethod == null) newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam);
+ if (job.checkerFramework.generateReturnsReceiver()) {
List<JCAnnotation> annotations = newMethod.mods.annotations;
if (annotations == null) annotations = List.nil();
- JCAnnotation anno = maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil());
- recursiveSetGeneratedBy(anno, source.get(), builderType.getContext());
+ JCAnnotation anno = maker.Annotation(genTypeRef(job.builderType, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil());
+ recursiveSetGeneratedBy(anno, job.sourceNode);
newMethod.mods.annotations = annotations.prepend(anno);
}
- injectMethod(builderType, newMethod);
+ injectMethod(job.builderType, newMethod);
}
private void addObtainVia(BuilderFieldData bfd, JavacNode node) {
@@ -1032,17 +1079,17 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
return null;
}
- private ListBuffer<JCExpression> getTypeParamExpressions(List<? extends JCTree> typeParams, JavacTreeMaker maker, Context context) {
+ private ListBuffer<JCExpression> getTypeParamExpressions(List<? extends JCTree> typeParams, JavacTreeMaker maker, JavacNode source) {
ListBuffer<JCExpression> typeParamsForBuilderParameter = new ListBuffer<JCExpression>();
for (JCTree typeParam : typeParams) {
if (typeParam instanceof JCTypeParameter) {
- typeParamsForBuilderParameter.add(maker.Ident(((JCTypeParameter)typeParam).getName()));
+ typeParamsForBuilderParameter.append(maker.Ident(((JCTypeParameter)typeParam).getName()));
} else if (typeParam instanceof JCIdent) {
- typeParamsForBuilderParameter.add(maker.Ident(((JCIdent)typeParam).getName()));
+ typeParamsForBuilderParameter.append(maker.Ident(((JCIdent)typeParam).getName()));
} else if (typeParam instanceof JCFieldAccess) {
- typeParamsForBuilderParameter.add(copySelect(maker, (JCFieldAccess) typeParam));
+ typeParamsForBuilderParameter.append(copySelect(maker, (JCFieldAccess) typeParam));
} else if (typeParam instanceof JCTypeApply) {
- typeParamsForBuilderParameter.add(cloneType(maker, (JCTypeApply)typeParam, typeParam, context));
+ typeParamsForBuilderParameter.append(cloneType(maker, (JCTypeApply)typeParam, source));
}
}
return typeParamsForBuilderParameter;
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilderRemove.java b/src/core/lombok/javac/handlers/HandleSuperBuilderRemove.java
index cca69729..d3db5ef4 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilderRemove.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilderRemove.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Project Lombok Authors.
+ * Copyright (C) 2020-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -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.core.AlreadyHandledAnnotations;
@@ -33,9 +31,10 @@ import lombok.core.HandlerPriority;
import lombok.experimental.SuperBuilder;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
+import lombok.spi.Provides;
-@ProviderFor(JavacAnnotationHandler.class)
-@HandlerPriority(65536)
+@Provides
+@HandlerPriority(32768)
@AlreadyHandledAnnotations
public class HandleSuperBuilderRemove extends JavacAnnotationHandler<SuperBuilder> {
@Override public void handle(AnnotationValues<SuperBuilder> annotation, JCAnnotation ast, JavacNode annotationNode) {
diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java
index 85dc7e80..0bf7cbe8 100644
--- a/src/core/lombok/javac/handlers/HandleSynchronized.java
+++ b/src/core/lombok/javac/handlers/HandleSynchronized.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
@@ -33,8 +33,7 @@ import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
@@ -46,13 +45,12 @@ import com.sun.tools.javac.tree.JCTree.JCNewArray;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
-import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
/**
* Handles the {@code lombok.Synchronized} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it.
public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
private static final String INSTANCE_LOCK_NAME = "$lock";
@@ -93,7 +91,6 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
}
JavacTreeMaker maker = methodNode.getTreeMaker().at(ast.pos);
- Context context = methodNode.getContext();
MemberExistsResult exists = MemberExistsResult.NOT_EXISTS;
@@ -124,7 +121,7 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
List.<JCExpression>of(maker.Literal(CTC_INT, 0)), null);
JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef(
maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (isStatic[0] ? Flags.STATIC : 0)),
- methodNode.toName(lockName), objectType, newObjectArray), ast, context);
+ methodNode.toName(lockName), objectType, newObjectArray), annotationNode);
injectFieldAndMarkGenerated(methodNode.up(), fieldDecl);
}
@@ -137,8 +134,8 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
lockNode = maker.Select(maker.Ident(methodNode.toName("this")), methodNode.toName(lockName));
}
- recursiveSetGeneratedBy(lockNode, ast, context);
- method.body = setGeneratedBy(maker.Block(0, List.<JCStatement>of(setGeneratedBy(maker.Synchronized(lockNode, method.body), ast, context))), ast, context);
+ recursiveSetGeneratedBy(lockNode, annotationNode);
+ method.body = setGeneratedBy(maker.Block(0, List.<JCStatement>of(setGeneratedBy(maker.Synchronized(lockNode, method.body), annotationNode))), annotationNode);
methodNode.rebuild();
}
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index ff0016e4..3fc6a4e4 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.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
@@ -38,11 +38,9 @@ import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
import com.sun.tools.javac.tree.JCTree.JCBlock;
@@ -60,7 +58,7 @@ import com.sun.tools.javac.util.List;
/**
* Handles the {@code ToString} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleToString extends JavacAnnotationHandler<ToString> {
@Override public void handle(AnnotationValues<ToString> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.TO_STRING_FLAG_USAGE, "@ToString");
@@ -135,7 +133,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
}
}
}
- JCMethodDecl method = createToString(typeNode, members, includeFieldNames, callSuper, fieldAccess, source.get());
+ JCMethodDecl method = createToString(typeNode, members, includeFieldNames, callSuper, fieldAccess, source);
injectMethod(typeNode, method);
break;
case EXISTS_BY_LOMBOK:
@@ -150,7 +148,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
}
static JCMethodDecl createToString(JavacNode typeNode, Collection<Included<JavacNode, ToString.Include>> members,
- boolean includeNames, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
+ boolean includeNames, boolean callSuper, FieldAccess fieldAccess, JavacNode source) {
JavacTreeMaker maker = typeNode.getTreeMaker();
@@ -250,7 +248,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
JCMethodDecl methodDef = maker.MethodDef(mods, typeNode.toName("toString"), returnType,
List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
createRelevantNonNullAnnotation(typeNode, methodDef);
- return recursiveSetGeneratedBy(methodDef, source, typeNode.getContext());
+ return recursiveSetGeneratedBy(methodDef, source);
}
public static String getTypeName(JavacNode typeNode) {
diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java
index 9ff33684..e006cc47 100644
--- a/src/core/lombok/javac/handlers/HandleUtilityClass.java
+++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -25,8 +25,6 @@ import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
import static lombok.javac.Javac.CTC_VOID;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-import org.mangosdk.spi.ProviderFor;
-
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
@@ -50,12 +48,13 @@ import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
+import lombok.spi.Provides;
/**
* Handles the {@code @UtilityClass} annotation for javac.
*/
@HandlerPriority(-4096) //-2^12; to ensure @FieldDefaults picks up on the 'static' we set here.
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> {
@Override public void handle(AnnotationValues<UtilityClass> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.UTILITY_CLASS_FLAG_USAGE, "@UtilityClass");
@@ -69,7 +68,7 @@ public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> {
private static boolean checkLegality(JavacNode typeNode, JavacNode errorNode) {
if (!isClass(typeNode)) {
- errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, annotation, or record).");
+ errorNode.addError("@UtilityClass is only supported on a class.");
return false;
}
@@ -141,7 +140,7 @@ public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> {
Name name = typeNode.toName("<init>");
JCBlock block = maker.Block(0L, createThrowStatement(typeNode, maker));
JCMethodDecl methodDef = maker.MethodDef(mods, name, null, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), block, null);
- JCMethodDecl constructor = recursiveSetGeneratedBy(methodDef, typeNode.get(), typeNode.getContext());
+ JCMethodDecl constructor = recursiveSetGeneratedBy(methodDef, typeNode);
JavacHandlerUtil.injectMethod(typeNode, constructor, List.<Type>nil(), Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
}
diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java
index 23c27bc0..7a524ca3 100644
--- a/src/core/lombok/javac/handlers/HandleVal.java
+++ b/src/core/lombok/javac/handlers/HandleVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2018 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -33,8 +33,7 @@ import lombok.javac.JavacASTVisitor;
import lombok.javac.JavacNode;
import lombok.javac.JavacResolution;
import lombok.javac.ResolutionResetNeeded;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symtab;
@@ -49,7 +48,7 @@ import com.sun.tools.javac.tree.JCTree.JCNewArray;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
-@ProviderFor(JavacASTVisitor.class)
+@Provides(JavacASTVisitor.class)
@HandlerPriority(HANDLE_DELEGATE_PRIORITY + 100) // run slightly after HandleDelegate; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated.
@ResolutionResetNeeded
public class HandleVal extends JavacASTAdapter {
@@ -63,6 +62,7 @@ public class HandleVal extends JavacASTAdapter {
JCTree typeTree = local.vartype;
if (typeTree == null) return;
String typeTreeToString = typeTree.toString();
+ JavacNode typeNode = localNode.getNodeFor(typeTree);
if (!(eq(typeTreeToString, "val") || eq(typeTreeToString, "var"))) return;
boolean isVal = typeMatches(val.class, localNode, typeTree);
@@ -111,7 +111,7 @@ public class HandleVal extends JavacASTAdapter {
if (isVal) local.mods.flags |= Flags.FINAL;
if (!localNode.shouldDeleteLombokAnnotations()) {
- JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeTree, localNode.getContext());
+ JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeNode);
local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation);
}
@@ -182,7 +182,7 @@ public class HandleVal extends JavacASTAdapter {
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
throw e;
} finally {
- recursiveSetGeneratedBy(local.vartype, typeTree, localNode.getContext());
+ recursiveSetGeneratedBy(local.vartype, typeNode);
}
}
}
diff --git a/src/core/lombok/javac/handlers/HandleValue.java b/src/core/lombok/javac/handlers/HandleValue.java
index abc5a5ca..cff29801 100644
--- a/src/core/lombok/javac/handlers/HandleValue.java
+++ b/src/core/lombok/javac/handlers/HandleValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2018 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
@@ -33,8 +33,7 @@ import lombok.Value;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
@@ -45,7 +44,7 @@ import com.sun.tools.javac.util.List;
/**
* Handles the {@code lombok.Value} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
@HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier.
public class HandleValue extends JavacAnnotationHandler<Value> {
private HandleFieldDefaults handleFieldDefaults = new HandleFieldDefaults();
@@ -72,7 +71,6 @@ public class HandleValue extends JavacAnnotationHandler<Value> {
JCModifiers jcm = ((JCClassDecl) typeNode.get()).mods;
if ((jcm.flags & Flags.FINAL) == 0) {
jcm.flags |= Flags.FINAL;
- typeNode.rebuild();
}
}
handleFieldDefaults.generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
diff --git a/src/core/lombok/javac/handlers/HandleWith.java b/src/core/lombok/javac/handlers/HandleWith.java
index 4e35a574..f914b4c7 100644
--- a/src/core/lombok/javac/handlers/HandleWith.java
+++ b/src/core/lombok/javac/handlers/HandleWith.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2020 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
@@ -37,8 +37,7 @@ import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
@@ -62,7 +61,7 @@ import com.sun.tools.javac.util.Name;
/**
* Handles the {@code lombok.With} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleWith extends JavacAnnotationHandler<With> {
public void generateWithForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelWith) {
if (checkForTypeLevelWith) {
@@ -215,6 +214,7 @@ public class HandleWith extends JavacAnnotationHandler<With> {
ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
Type returnType = sym == null ? null : sym.type;
+ recursiveSetGeneratedBy(createdWith, source);
injectMethod(typeNode, createdWith, List.<Type>of(getMirrorForFieldType(fieldNode)), returnType);
}
@@ -234,7 +234,7 @@ public class HandleWith extends JavacAnnotationHandler<With> {
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(copyableAnnotations);
- JCExpression pType = cloneType(maker, fieldDecl.vartype, source.get(), source.getContext());
+ JCExpression pType = cloneType(maker, fieldDecl.vartype, source);
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, pType, null);
if (!makeAbstract) {
@@ -289,7 +289,7 @@ public class HandleWith extends JavacAnnotationHandler<With> {
if (makeAbstract) access = access | Flags.ABSTRACT;
JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType,
- methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
+ methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
copyJavadoc(field, decl, CopyJavadoc.WITH);
return decl;
}
diff --git a/src/core/lombok/javac/handlers/HandleWithBy.java b/src/core/lombok/javac/handlers/HandleWithBy.java
index 19673172..f1f953b3 100644
--- a/src/core/lombok/javac/handlers/HandleWithBy.java
+++ b/src/core/lombok/javac/handlers/HandleWithBy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Project Lombok Authors.
+ * Copyright (C) 2020-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -41,8 +41,7 @@ import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.JavacTreeMaker.TypeTag;
import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
@@ -67,7 +66,7 @@ import com.sun.tools.javac.util.Name;
/**
* Handles the {@code lombok.With} annotation for javac.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@Provides
public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
public void generateWithByForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelWithBy) {
if (checkForTypeLevelWithBy) {
@@ -126,7 +125,6 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
@Override public void handle(AnnotationValues<WithBy> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.WITHBY_FLAG_USAGE, "@WithBy");
- Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields();
deleteAnnotationIfNeccessary(annotationNode, WithBy.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode node = annotationNode.up();
@@ -138,7 +136,7 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
switch (node.getKind()) {
case FIELD:
- createWithByForFields(level, fields, annotationNode, true, onMethod);
+ createWithByForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod);
break;
case TYPE:
if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @WithBy on a type.");
@@ -209,6 +207,7 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
Type returnType = sym == null ? null : sym.type;
+ recursiveSetGeneratedBy(createdWithBy, source);
injectMethod(typeNode, createdWithBy, List.<Type>of(getMirrorForFieldType(fieldNode)), returnType);
}
@@ -265,7 +264,7 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
}
if (functionalInterfaceName == null) {
functionalInterfaceName = NAME_JUF_FUNCTION;
- parameterizer = cloneType(maker, fieldDecl.vartype, source.get(), field.getContext());
+ parameterizer = cloneType(maker, fieldDecl.vartype, source);
}
if (functionalInterfaceName == NAME_JUF_INTOP) applyMethodName = "applyAsInt";
if (functionalInterfaceName == NAME_JUF_LONGOP) applyMethodName = "applyAsLong";
@@ -274,7 +273,7 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
JCExpression varType = chainDots(field, functionalInterfaceName);
if (parameterizer != null && superExtendsStyle) {
JCExpression parameterizer1 = parameterizer;
- JCExpression parameterizer2 = cloneType(maker, parameterizer, source.get(), field.getContext());
+ JCExpression parameterizer2 = cloneType(maker, parameterizer, source);
// TODO: Apply copyable annotations to 'parameterizer' and 'parameterizer2'.
JCExpression arg1 = maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), parameterizer1);
JCExpression arg2 = maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), parameterizer2);
@@ -334,7 +333,7 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
if (makeAbstract) access = access | Flags.ABSTRACT;
createRelevantNonNullAnnotation(source, param);
JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType,
- methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
+ methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
copyJavadoc(field, decl, CopyJavadoc.WITH_BY);
createRelevantNonNullAnnotation(source, decl);
return decl;
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index cd4bc70a..b4f2acc4 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.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
@@ -35,7 +35,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.lang.model.element.Element;
@@ -103,7 +102,6 @@ import lombok.core.handlers.HandlerUtil.FieldAccess;
import lombok.delombok.LombokOptionsFactory;
import lombok.experimental.Accessors;
import lombok.experimental.Tolerate;
-import lombok.javac.Java14Flags;
import lombok.javac.Javac;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -118,17 +116,15 @@ public class JavacHandlerUtil {
}
private static class MarkingScanner extends TreeScanner {
- private final JCTree source;
- private final Context context;
+ private final JavacNode source;
- MarkingScanner(JCTree source, Context context) {
+ MarkingScanner(JavacNode source) {
this.source = source;
- this.context = context;
}
@Override public void scan(JCTree tree) {
if (tree == null) return;
- setGeneratedBy(tree, source, context);
+ setGeneratedBy(tree, source);
super.scan(tree);
}
}
@@ -146,12 +142,12 @@ public class JavacHandlerUtil {
Options options = Options.instance(context);
return (options.keySet().contains("ide") && !options.keySet().contains("backgroundCompilation"));
}
-
+
public static boolean inNetbeansCompileOnSave(Context context) {
Options options = Options.instance(context);
return (options.keySet().contains("ide") && options.keySet().contains("backgroundCompilation"));
}
-
+
public static JCTree getGeneratedBy(JCTree node) {
return JCTree_generatedNode.get(node);
}
@@ -160,20 +156,31 @@ public class JavacHandlerUtil {
return getGeneratedBy(node) != null;
}
- public static <T extends JCTree> T recursiveSetGeneratedBy(T node, JCTree source, Context context) {
+ public static <T extends JCTree> T recursiveSetGeneratedBy(T node, JavacNode source) {
if (node == null) return null;
- setGeneratedBy(node, source, context);
- node.accept(new MarkingScanner(source, context));
+ setGeneratedBy(node, source);
+ node.accept(new MarkingScanner(source));
return node;
}
- public static <T extends JCTree> T setGeneratedBy(T node, JCTree source, Context context) {
+ public static <T extends JCTree> T setGeneratedBy(T node, JavacNode sourceNode) {
if (node == null) return null;
- if (source == null) JCTree_generatedNode.clear(node);
- else JCTree_generatedNode.set(node, source);
- if (source != null && (!inNetbeansEditor(context) || (node instanceof JCVariableDecl && (((JCVariableDecl) node).mods.flags & Flags.PARAMETER) != 0))) node.pos = source.pos;
+ if (sourceNode == null) {
+ JCTree_generatedNode.clear(node);
+ return node;
+ }
+ JCTree_generatedNode.set(node, sourceNode.get());
+
+ if (!inNetbeansEditor(sourceNode.getContext()) || isParameter(node)) {
+ node.pos = sourceNode.getStartPos();
+ storeEnd(node, sourceNode.getEndPosition(), (JCCompilationUnit) sourceNode.top().get());
+ }
return node;
}
+
+ public static boolean isParameter(JCTree node) {
+ return node instanceof JCVariableDecl && (((JCVariableDecl) node).mods.flags & Flags.PARAMETER) != 0;
+ }
public static boolean hasAnnotation(String type, JavacNode node) {
return hasAnnotation(type, node, false);
@@ -800,7 +807,7 @@ public class JavacHandlerUtil {
node = upToTypeNode(node);
if (node != null && node.get() instanceof JCClassDecl) {
- for (JCTree def : ((JCClassDecl)node.get()).defs) {
+ for (JCTree def : ((JCClassDecl) node.get()).defs) {
if (def instanceof JCMethodDecl) {
JCMethodDecl md = (JCMethodDecl) def;
if (md.name.contentEquals("<init>")) {
@@ -816,23 +823,21 @@ public class JavacHandlerUtil {
}
/**
- * Checks if there is a constructor generated by lombok.
+ * Checks if there is at least one constructor that is generated by lombok.
*
- * @param node Any node that represents the Type (JCClassDecl) to look in, or any child node thereof.
+ * @param node Any node that represents the Type (TypeDeclaration) to look in, or any child node thereof.
*/
public static boolean lombokConstructorExists(JavacNode node) {
node = upToTypeNode(node);
if (node != null && node.get() instanceof JCClassDecl) {
- for (JCTree def : ((JCClassDecl)node.get()).defs) {
+ for (JCTree def : ((JCClassDecl) node.get()).defs) {
if (def instanceof JCMethodDecl) {
JCMethodDecl md = (JCMethodDecl) def;
if (md.name.contentEquals("<init>")) {
if ((md.mods.flags & Flags.GENERATEDCONSTR) != 0) continue;
if (isTolerate(node, md)) continue;
- if (getGeneratedBy(def) != null) {
- return true;
- }
+ if (getGeneratedBy(def) != null) return true;
}
}
}
@@ -1054,7 +1059,7 @@ public class JavacHandlerUtil {
public static JavacNode injectField(JavacNode typeNode, JCVariableDecl field) {
return injectField(typeNode, field, false);
}
-
+
public static JavacNode injectField(JavacNode typeNode, JCVariableDecl field, boolean addGenerated) {
return injectField(typeNode, field, addGenerated, false);
}
@@ -1063,8 +1068,8 @@ public class JavacHandlerUtil {
JCClassDecl type = (JCClassDecl) typeNode.get();
if (addGenerated) {
- addSuppressWarningsAll(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext());
- addGenerated(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext());
+ addSuppressWarningsAll(field.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(field)), typeNode.getContext());
+ addGenerated(field.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(field)), typeNode.getContext());
}
List<JCTree> insertAfter = null;
@@ -1104,6 +1109,17 @@ public class JavacHandlerUtil {
private static Constructor<?> CONSTRUCTOR;
private static Field ANNOTATIONS, UNDERLYING_TYPE;
+ private static void initByLoader(ClassLoader classLoader) {
+ if (TYPE != null) return;
+ Class<?> c;
+ try {
+ c = classLoader.loadClass("com.sun.tools.javac.tree.JCTree$JCAnnotatedType");
+ } catch (Exception e) {
+ return;
+ }
+ init(c);
+ }
+
private static void init(Class<?> in) {
if (TYPE != null) return;
if (!in.getName().equals("com.sun.tools.javac.tree.JCTree$JCAnnotatedType")) return;
@@ -1148,17 +1164,18 @@ public class JavacHandlerUtil {
}
static JCExpression create(List<JCAnnotation> annotations, JCExpression underlyingType) {
+ initByLoader(underlyingType.getClass().getClassLoader());
try {
return (JCExpression) CONSTRUCTOR.newInstance(annotations, underlyingType);
} catch (Exception e) {
- return null;
+ return underlyingType;
}
}
}
-
+
static class JCAnnotationReflect {
private static Field ATTRIBUTE;
-
+
static {
try {
ATTRIBUTE = Permit.getField(JCAnnotation.class, "attribute");
@@ -1199,7 +1216,7 @@ public class JavacHandlerUtil {
try {
Scope scope = (Scope) membersField.get(from);
if (scope == null) return;
- removeMethod.invoke(scope, toRemove);
+ Permit.invoke(removeMethod, scope, toRemove);
} catch (Exception e) {}
}
@@ -1208,7 +1225,7 @@ public class JavacHandlerUtil {
try {
Scope scope = (Scope) membersField.get(from);
if (scope == null) return;
- enterMethod.invoke(scope, toEnter);
+ Permit.invoke(enterMethod, scope, toEnter);
} catch (Exception e) {}
}
}
@@ -1227,7 +1244,7 @@ public class JavacHandlerUtil {
Context context = typeNode.getContext();
Symtab symtab = Symtab.instance(context);
JCClassDecl type = (JCClassDecl) typeNode.get();
-
+
if (method.getName().contentEquals("<init>")) {
//Scan for default constructor, and remove it.
int idx = 0;
@@ -1244,11 +1261,11 @@ public class JavacHandlerUtil {
idx++;
}
}
-
- addSuppressWarningsAll(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
- addGenerated(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
+
+ addSuppressWarningsAll(method.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(method)), typeNode.getContext());
+ addGenerated(method.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(method)), typeNode.getContext());
type.defs = type.defs.append(method);
-
+
List<Symbol.VarSymbol> params = null;
if (method.getParameters() != null && !method.getParameters().isEmpty()) {
ListBuffer<Symbol.VarSymbol> newParams = new ListBuffer<Symbol.VarSymbol>();
@@ -1257,6 +1274,7 @@ public class JavacHandlerUtil {
if (param.sym == null) {
Type paramType = paramTypes == null ? param.getType().type : paramTypes.get(i);
VarSymbol varSymbol = new VarSymbol(param.mods.flags, param.name, paramType, symtab.noSymbol);
+ varSymbol.adr = 1 << i;
List<JCAnnotation> annotations = param.getModifiers().getAnnotations();
if (annotations != null && !annotations.isEmpty()) {
ListBuffer<Attribute.Compound> newAnnotations = new ListBuffer<Attribute.Compound>();
@@ -1278,9 +1296,9 @@ public class JavacHandlerUtil {
params = newParams.toList();
if (params.length() != method.getParameters().length()) params = null;
}
-
+
fixMethodMirror(typeNode.getContext(), typeNode.getElement(), method.getModifiers().flags, method.getName(), paramTypes, params, returnType);
-
+
typeNode.add(method, Kind.METHOD);
}
@@ -1290,6 +1308,9 @@ public class JavacHandlerUtil {
MethodSymbol methodSymbol = new MethodSymbol(access, methodName, new MethodType(paramTypes, returnType, List.<Type>nil(), Symtab.instance(context).methodClass), cs);
if (params != null && !params.isEmpty()) {
methodSymbol.params = params;
+ for (VarSymbol varSymbol : params) {
+ varSymbol.owner = methodSymbol;
+ }
}
ClassSymbolMembersField.enter(cs, methodSymbol);
}
@@ -1303,8 +1324,8 @@ public class JavacHandlerUtil {
*/
public static JavacNode injectType(JavacNode typeNode, final JCClassDecl type) {
JCClassDecl typeDecl = (JCClassDecl) typeNode.get();
- addSuppressWarningsAll(type.mods, typeNode, type.pos, getGeneratedBy(type), typeNode.getContext());
- addGenerated(type.mods, typeNode, type.pos, getGeneratedBy(type), typeNode.getContext());
+ addSuppressWarningsAll(type.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(type)), typeNode.getContext());
+ addGenerated(type.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(type)), typeNode.getContext());
typeDecl.defs = typeDecl.defs.append(type);
return typeNode.add(type, Kind.TYPE);
}
@@ -1343,7 +1364,7 @@ public class JavacHandlerUtil {
}
}
- public static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) {
+ public static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, JavacNode source, Context context) {
if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateSuppressWarnings()) return;
boolean addJLSuppress = !Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS));
@@ -1359,27 +1380,27 @@ public class JavacHandlerUtil {
}
}
}
- if (addJLSuppress) addAnnotation(mods, node, pos, source, context, "java.lang.SuppressWarnings", node.getTreeMaker().Literal("all"));
+ if (addJLSuppress) addAnnotation(mods, node, source, "java.lang.SuppressWarnings", node.getTreeMaker().Literal("all"));
if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_FINDBUGS_SUPPRESSWARNINGS_ANNOTATIONS))) {
JavacTreeMaker maker = node.getTreeMaker();
JCExpression arg = maker.Assign(maker.Ident(node.toName("justification")), maker.Literal("generated code"));
- addAnnotation(mods, node, pos, source, context, "edu.umd.cs.findbugs.annotations.SuppressFBWarnings", arg);
+ addAnnotation(mods, node, source, "edu.umd.cs.findbugs.annotations.SuppressFBWarnings", arg);
}
}
- public static void addGenerated(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) {
+ public static void addGenerated(JCModifiers mods, JavacNode node, JavacNode source, Context context) {
if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateGenerated()) return;
if (HandlerUtil.shouldAddGenerated(node)) {
- addAnnotation(mods, node, pos, source, context, "javax.annotation.Generated", node.getTreeMaker().Literal("lombok"));
+ addAnnotation(mods, node, source, "javax.annotation.Generated", node.getTreeMaker().Literal("lombok"));
}
if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_LOMBOK_GENERATED_ANNOTATIONS))) {
- addAnnotation(mods, node, pos, source, context, "lombok.Generated", null);
+ addAnnotation(mods, node, source, "lombok.Generated", null);
}
}
- public static void addAnnotation(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context, String annotationTypeFqn, JCExpression arg) {
+ public static void addAnnotation(JCModifiers mods, JavacNode node, JavacNode source, String annotationTypeFqn, JCExpression arg) {
boolean isJavaLangBased;
String simpleName; {
int idx = annotationTypeFqn.lastIndexOf('.');
@@ -1402,17 +1423,8 @@ public class JavacHandlerUtil {
JavacTreeMaker maker = node.getTreeMaker();
JCExpression annType = isJavaLangBased ? genJavaLangTypeRef(node, simpleName) : chainDotsString(node, annotationTypeFqn);
- annType.pos = pos;
- if (arg != null) {
- arg.pos = pos;
- if (arg instanceof JCAssign) {
- ((JCAssign) arg).lhs.pos = pos;
- ((JCAssign) arg).rhs.pos = pos;
- }
- }
List<JCExpression> argList = arg != null ? List.of(arg) : List.<JCExpression>nil();
- JCAnnotation annotation = recursiveSetGeneratedBy(maker.Annotation(annType, argList), source, context);
- annotation.pos = pos;
+ JCAnnotation annotation = recursiveSetGeneratedBy(maker.Annotation(annType, argList), source);
mods.annotations = mods.annotations.append(annotation);
}
@@ -1456,6 +1468,7 @@ public class JavacHandlerUtil {
}
return e;
}
+
/**
* In javac, dotted access of any kind, from {@code java.lang.String} to {@code var.methodName}
* is represented by a fold-left of {@code Select} nodes with the leftmost string represented by
@@ -1831,13 +1844,12 @@ public class JavacHandlerUtil {
if (params == null || params.isEmpty()) return params;
ListBuffer<JCTypeParameter> out = new ListBuffer<JCTypeParameter>();
JavacTreeMaker maker = source.getTreeMaker();
- Context context = source.getContext();
for (JCTypeParameter tp : params) {
List<JCExpression> bounds = tp.bounds;
if (bounds != null && !bounds.isEmpty()) {
ListBuffer<JCExpression> boundsCopy = new ListBuffer<JCExpression>();
for (JCExpression expr : tp.bounds) {
- boundsCopy.append(cloneType(maker, expr, source.get(), context));
+ boundsCopy.append(cloneType(maker, expr, source));
}
bounds = boundsCopy.toList();
}
@@ -1859,20 +1871,30 @@ public class JavacHandlerUtil {
public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, JavacNode type, List<JCTypeParameter> params) {
JCClassDecl td = (JCClassDecl) type.get();
boolean instance = (td.mods.flags & Flags.STATIC) == 0;
- return namePlusTypeParamsToTypeReference(maker, type.up(), td.name, instance, params);
+ return namePlusTypeParamsToTypeReference(maker, type.up(), td.name, instance, params, List.<JCAnnotation>nil());
+ }
+
+ public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, JavacNode type, List<JCTypeParameter> params, List<JCAnnotation> annotations) {
+ JCClassDecl td = (JCClassDecl) type.get();
+ boolean instance = (td.mods.flags & Flags.STATIC) == 0;
+ return namePlusTypeParamsToTypeReference(maker, type.up(), td.name, instance, params, annotations);
}
public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, JavacNode parentType, Name typeName, boolean instance, List<JCTypeParameter> params) {
+ return namePlusTypeParamsToTypeReference(maker, parentType, typeName, instance, params, List.<JCAnnotation>nil());
+ }
+
+ public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, JavacNode parentType, Name typeName, boolean instance, List<JCTypeParameter> params, List<JCAnnotation> annotations) {
JCExpression r = null;
-
if (parentType != null && parentType.getKind() == Kind.TYPE) {
JCClassDecl td = (JCClassDecl) parentType.get();
boolean outerInstance = instance && ((td.mods.flags & Flags.STATIC) == 0);
List<JCTypeParameter> outerParams = instance ? td.typarams : List.<JCTypeParameter>nil();
- r = namePlusTypeParamsToTypeReference(maker, parentType.up(), td.name, outerInstance, outerParams);
+ r = namePlusTypeParamsToTypeReference(maker, parentType.up(), td.name, outerInstance, outerParams, List.<JCAnnotation>nil());
}
r = r == null ? maker.Ident(typeName) : maker.Select(r, typeName);
+ if (!annotations.isEmpty()) r = JCAnnotatedTypeReflect.create(annotations, r);
if (!params.isEmpty()) r = maker.TypeApply(r, typeParameterNames(maker, params));
return r;
}
@@ -1926,17 +1948,30 @@ public class JavacHandlerUtil {
return out.toList();
}
- static boolean isClass(JavacNode typeNode) {
- return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION | Java14Flags.RECORD);
+ /**
+ * Returns {@code true} if the provided node is an actual class and not some other type declaration (so, not an annotation definition, interface, enum, or record).
+ */
+ public static boolean isClass(JavacNode typeNode) {
+ return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION | RECORD);
+ }
+
+ /**
+ * Returns {@code true} if the provided node is an actual class or enum and not some other type declaration (so, not an annotation definition, interface, or record).
+ */
+ public static boolean isClassOrEnum(JavacNode typeNode) {
+ return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION | RECORD);
}
- static boolean isClassOrEnum(JavacNode typeNode) {
- return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION | Java14Flags.RECORD);
+ /**
+ * Returns {@code true} if the provided node is a record declaration (so, not an annotation definition, interface, enum, or plain class).
+ */
+ public static boolean isRecord(JavacNode typeNode) {
+ return typeNode.getKind() == Kind.TYPE && (((JCClassDecl) typeNode.get()).mods.flags & RECORD) != 0;
}
public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, long flags) {
JCClassDecl typeDecl = null;
- if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl)typeNode.get();
+ if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
else return false;
long typeDeclflags = typeDecl == null ? 0 : typeDecl.mods.flags;
@@ -1950,11 +1985,11 @@ public class JavacHandlerUtil {
return node;
}
- public static List<JCExpression> cloneTypes(JavacTreeMaker maker, List<JCExpression> in, JCTree source, Context context) {
+ public static List<JCExpression> cloneTypes(JavacTreeMaker maker, List<JCExpression> in, JavacNode source) {
if (in.isEmpty()) return List.nil();
- if (in.size() == 1) return List.of(cloneType(maker, in.get(0), source, context));
+ if (in.size() == 1) return List.of(cloneType(maker, in.get(0), source));
ListBuffer<JCExpression> lb = new ListBuffer<JCExpression>();
- for (JCExpression expr : in) lb.append(cloneType(maker, expr, source, context));
+ for (JCExpression expr : in) lb.append(cloneType(maker, expr, source));
return lb.toList();
}
@@ -1968,9 +2003,9 @@ public class JavacHandlerUtil {
* the class's own parameter, but as its a static method, the static method's notion of {@code T} is different from the class notion of {@code T}. If you're duplicating
* a type used in the class context, you need to use this method.
*/
- public static JCExpression cloneType(JavacTreeMaker maker, JCExpression in, JCTree source, Context context) {
+ public static JCExpression cloneType(JavacTreeMaker maker, JCExpression in, JavacNode source) {
JCExpression out = cloneType0(maker, in);
- if (out != null) recursiveSetGeneratedBy(out, source, context);
+ if (out != null) recursiveSetGeneratedBy(out, source);
return out;
}
@@ -2031,50 +2066,6 @@ public class JavacHandlerUtil {
return (JCExpression) in;
}
- private static final Pattern SECTION_FINDER = Pattern.compile("^\\s*\\**\\s*[-*][-*]+\\s*([GS]ETTER|WITH(?:ER)?)\\s*[-*][-*]+\\s*\\**\\s*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
- private static final Pattern LINE_BREAK_FINDER = Pattern.compile("(\\r?\\n)?");
-
- public static String stripLinesWithTagFromJavadoc(String javadoc, String regexpFragment) {
- Pattern p = Pattern.compile("^\\s*\\**\\s*" + regexpFragment + "\\s*\\**\\s*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
- Matcher m = p.matcher(javadoc);
- return m.replaceAll("");
- }
-
- public static String stripSectionsFromJavadoc(String javadoc) {
- Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
- if (!sectionMatcher.find()) return javadoc;
-
- return javadoc.substring(0, sectionMatcher.start());
- }
-
- public static String getJavadocSection(String javadoc, String sectionNameSpec) {
- String[] sectionNames = sectionNameSpec.split("\\|");
- Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
- Matcher lineBreakMatcher = LINE_BREAK_FINDER.matcher(javadoc);
- int sectionStart = -1;
- int sectionEnd = -1;
- while (sectionMatcher.find()) {
- boolean found = false;
- for (String sectionName : sectionNames) if (sectionMatcher.group(1).equalsIgnoreCase(sectionName)) {
- found = true;
- break;
- }
- if (found) {
- lineBreakMatcher.find(sectionMatcher.end());
- sectionStart = lineBreakMatcher.end();
- } else if (sectionStart != -1) {
- sectionEnd = sectionMatcher.start();
- }
- }
-
- if (sectionStart != -1) {
- if (sectionEnd != -1) return javadoc.substring(sectionStart, sectionEnd);
- return javadoc.substring(sectionStart);
- }
-
- return null;
- }
-
public static enum CopyJavadoc {
VERBATIM {
@Override public String apply(final JCCompilationUnit cu, final JavacNode node) {
@@ -2089,7 +2080,7 @@ public class JavacHandlerUtil {
String out = getJavadocSection(javadoc, "GETTER");
final boolean sectionBased = out != null;
if (!sectionBased) {
- out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@param(?:eter)?\\s+.*");
+ out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), JavadocTag.PARAM);
}
node.getAst().cleanupTask("javadocfilter-getter", n, new CleanupTask() {
@Override public void cleanup() {
@@ -2097,7 +2088,7 @@ public class JavacHandlerUtil {
if (javadoc == null || javadoc.isEmpty()) return;
javadoc = stripSectionsFromJavadoc(javadoc);
if (!sectionBased) {
- javadoc = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@returns?\\s+.*");
+ javadoc = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), JavadocTag.RETURN);
}
Javac.setDocComment(cu, n, javadoc);
}
@@ -2130,7 +2121,7 @@ public class JavacHandlerUtil {
String out = getJavadocSection(javadoc, sectionName);
final boolean sectionBased = out != null;
if (!sectionBased) {
- out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@returns?\\s+.*");
+ out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), JavadocTag.RETURN);
}
node.getAst().cleanupTask("javadocfilter-setter", n, new CleanupTask() {
@Override public void cleanup() {
@@ -2138,7 +2129,7 @@ public class JavacHandlerUtil {
if (javadoc == null || javadoc.isEmpty()) return;
javadoc = stripSectionsFromJavadoc(javadoc);
if (!sectionBased) {
- javadoc = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@param(?:eter)?\\s+.*");
+ javadoc = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), JavadocTag.PARAM);
}
Javac.setDocComment(cu, n, javadoc);
}
@@ -2150,6 +2141,7 @@ public class JavacHandlerUtil {
public static void copyJavadoc(JavacNode from, JCTree to, CopyJavadoc copyMode) {
copyJavadoc(from, to, copyMode, false);
}
+
/**
* Copies javadoc on one node to the other.
*
@@ -2164,31 +2156,13 @@ public class JavacHandlerUtil {
try {
JCCompilationUnit cu = ((JCCompilationUnit) from.top().get());
String newJavadoc = copyMode.apply(cu, from);
- if (newJavadoc != null) {
- if (forceAddReturn) newJavadoc = addReturnsThisIfNeeded(newJavadoc);
- Javac.setDocComment(cu, to, newJavadoc);
+ if (forceAddReturn) {
+ newJavadoc = addReturnsThisIfNeeded(newJavadoc);
}
+ Javac.setDocComment(cu, to, newJavadoc);
} catch (Exception ignore) {}
}
- private static final Pattern FIND_RETURN = Pattern.compile("^\\s*\\**\\s*@returns?\\s+.*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
- static String addReturnsThisIfNeeded(String in) {
- if (FIND_RETURN.matcher(in).find()) return in;
-
- return addJavadocLine(in, "@return {@code this}.");
- }
-
- static String addReturnsUpdatedSelfIfNeeded(String in) {
- if (FIND_RETURN.matcher(in).find()) return in;
-
- return addJavadocLine(in, "@return a clone of this object, except with this updated property (returns {@code this} if an identical value is passed).");
- }
-
- static String addJavadocLine(String in, String line) {
- if (in.endsWith("\n")) return in + line + "\n";
- return in + "\n" + line;
- }
-
public static boolean isDirectDescendantOfObject(JavacNode typeNode) {
if (!(typeNode.get() instanceof JCClassDecl)) throw new IllegalArgumentException("not a type node");
JCTree extending = Javac.getExtendsClause((JCClassDecl) typeNode.get());
@@ -2232,6 +2206,10 @@ public class JavacHandlerUtil {
JCExpression resType = mth.restype;
if (resType instanceof JCTypeApply) {
JCTypeApply ta = (JCTypeApply) resType;
+ if (ta.clazz instanceof JCFieldAccess) {
+ mth.restype = maker.TypeApply(maker.AnnotatedType(List.of(m), ta.clazz), ta.arguments);
+ return;
+ }
resType = ta.clazz;
}
@@ -2287,8 +2265,4 @@ public class JavacHandlerUtil {
arg.mods.annotations = arg.mods.annotations == null ? List.of(m) : arg.mods.annotations.prepend(m);
}
}
-
- public static boolean isRecord(JavacNode typeNode) {
- return typeNode.getKind() == Kind.TYPE && (((JCClassDecl) typeNode.get()).mods.flags & Java14Flags.RECORD) != 0;
- }
}
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index 7cd52c8c..4ca09b82 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2020 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -43,7 +43,6 @@ import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
-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.Name;
@@ -57,6 +56,7 @@ import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.HandleBuilder.BuilderJob;
public class JavacSingularsRecipes {
public interface ExpressionMaker {
@@ -235,7 +235,7 @@ public class JavacSingularsRecipes {
return Arrays.asList(p, s);
}
- public abstract java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source);
+ public abstract java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JavacNode source);
/**
* Generates the singular, plural, and clear methods for the given {@link SingularData}.
@@ -243,36 +243,38 @@ public class JavacSingularsRecipes {
* If you need more control over the return type and value, use
* {@link #generateMethods(SingularData, boolean, JavacNode, JCTree, boolean, ExpressionMaker, StatementMaker)}.
*/
- public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, final JavacNode builderType, JCTree source, boolean fluent, final boolean chain, AccessLevel access) {
- final JavacTreeMaker maker = builderType.getTreeMaker();
+ public void generateMethods(final BuilderJob job, SingularData data, boolean deprecate) {
+ //job.checkerFramework, job.builderType, job.source, job.oldFluent, job.oldChain, job.accessInners
+ //CheckerFrameworkVersion cfv, final JavacNode builderType, JavacNode source, boolean fluent, final boolean chain, AccessLevel access) {
+ final JavacTreeMaker maker = job.builderType.getTreeMaker();
ExpressionMaker returnTypeMaker = new ExpressionMaker() { @Override public JCExpression make() {
- return chain ?
- cloneSelfType(builderType) :
- maker.Type(createVoidType(builderType.getSymbolTable(), CTC_VOID));
+ return job.oldChain ?
+ cloneSelfType(job.builderType) :
+ maker.Type(createVoidType(job.builderType.getSymbolTable(), CTC_VOID));
}};
StatementMaker returnStatementMaker = new StatementMaker() { @Override public JCStatement make() {
- return chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ return job.oldChain ? maker.Return(maker.Ident(job.builderType.toName("this"))) : null;
}};
- generateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
+ generateMethods(job.checkerFramework, data, deprecate, job.builderType, job.sourceNode, job.oldFluent, returnTypeMaker, returnStatementMaker, job.accessInners);
}
/**
* Generates the singular, plural, and clear methods for the given {@link SingularData}.
* Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods.
*/
- public abstract void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access);
+ public abstract void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JavacNode source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access);
- protected void doGenerateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ protected void doGenerateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JavacNode source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
JavacTreeMaker maker = builderType.getTreeMaker();
generateSingularMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent, access);
generatePluralMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, fluent, access);
generateClearMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, access);
}
- private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, List<JCAnnotation> methodAnnotations, AccessLevel access, Boolean ignoreNullCollections) {
+ private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JavacNode source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, List<JCAnnotation> methodAnnotations, AccessLevel access, Boolean ignoreNullCollections) {
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access, methodAnnotations);
@@ -288,15 +290,15 @@ public class JavacSingularsRecipes {
}
JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, jcVariableDecls, thrown, body, null);
- recursiveSetGeneratedBy(method, source, builderType.getContext());
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, method);
+ recursiveSetGeneratedBy(method, source);
injectMethod(builderType, method);
}
- private void generateClearMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, AccessLevel access) {
+ private void generateClearMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JavacNode source, AccessLevel access) {
JCStatement clearStatement = generateClearStatements(maker, data, builderType);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- statements.add(clearStatement);
+ statements.append(clearStatement);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil(), List.<JCAnnotation>nil(), access, null);
@@ -304,7 +306,7 @@ public class JavacSingularsRecipes {
protected abstract JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType);
- private void generateSingularMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) {
+ private void generateSingularMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JavacNode source, boolean fluent, AccessLevel access) {
ListBuffer<JCStatement> statements = generateSingularMethodStatements(maker, data, builderType, source);
List<JCVariableDecl> params = generateSingularMethodParameters(maker, data, builderType, source);
Name name = data.getSingularName();
@@ -317,7 +319,7 @@ public class JavacSingularsRecipes {
finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, methodAnnotations, access, null);
}
- protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, Name name) {
+ protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source, Name name) {
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
JCExpression type = cloneParamType(typeIndex, maker, data.getTypeArgs(), builderType, source);
List<JCAnnotation> typeUseAnns = getTypeUseAnnotations(type);
@@ -332,11 +334,11 @@ public class JavacSingularsRecipes {
return maker.Exec(invokeAdd);
}
- protected abstract ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source);
+ protected abstract ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source);
- protected abstract List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source);
+ protected abstract List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source);
- private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) {
+ private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JavacNode source, boolean fluent, AccessLevel access) {
ListBuffer<JCStatement> statements = generatePluralMethodStatements(maker, data, builderType, source);
Name name = data.getPluralName();
@@ -355,7 +357,7 @@ public class JavacSingularsRecipes {
JCExpression incomingIsNotNull = maker.Binary(CTC_NOT_EQUAL, maker.Ident(data.getPluralName()), maker.Literal(CTC_BOT, null));
JCStatement onNotNull = maker.Block(0, statements.toList());
statements = new ListBuffer<JCStatement>();
- statements.add(maker.If(incomingIsNotNull, onNotNull, null));
+ statements.append(maker.If(incomingIsNotNull, onNotNull, null));
} else {
statements.prepend(JavacHandlerUtil.generateNullCheck(maker, null, data.getPluralName(), builderType, "%s cannot be null"));
}
@@ -365,7 +367,7 @@ public class JavacSingularsRecipes {
finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), methodAnnotations, access, ignoreNullCollections);
}
- protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName() + "All");
@@ -377,9 +379,9 @@ public class JavacSingularsRecipes {
protected abstract JCExpression getPluralMethodParamType(JavacNode builderType);
- protected abstract JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source);
+ protected abstract JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source);
- public abstract void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable);
+ public abstract void appendBuildCode(SingularData data, JavacNode builderType, JavacNode source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable);
public boolean shadowedDuringBuild() {
return true;
@@ -393,7 +395,7 @@ public class JavacSingularsRecipes {
}
}
- public void appendCleaningCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements) {
+ public void appendCleaningCode(SingularData data, JavacNode builderType, JavacNode source, ListBuffer<JCStatement> statements) {
}
// -- Utility methods --
@@ -409,16 +411,15 @@ public class JavacSingularsRecipes {
* @param typeArgs the list of type args to clone.
* @param source The source annotation that is the root cause of this code generation.
*/
- protected JCExpression addTypeArgs(int count, boolean addExtends, JavacNode node, JCExpression type, List<JCExpression> typeArgs, JCTree source) {
+ protected JCExpression addTypeArgs(int count, boolean addExtends, JavacNode node, JCExpression type, List<JCExpression> typeArgs, JavacNode source) {
JavacTreeMaker maker = node.getTreeMaker();
List<JCExpression> clonedAndFixedTypeArgs = createTypeArgs(count, addExtends, node, typeArgs, source);
return maker.TypeApply(type, clonedAndFixedTypeArgs);
}
- protected List<JCExpression> createTypeArgs(int count, boolean addExtends, JavacNode node, List<JCExpression> typeArgs, JCTree source) {
+ protected List<JCExpression> createTypeArgs(int count, boolean addExtends, JavacNode node, List<JCExpression> typeArgs, JavacNode source) {
JavacTreeMaker maker = node.getTreeMaker();
- Context context = node.getContext();
if (count < 0) throw new IllegalArgumentException("count is negative");
if (count == 0) return List.nil();
@@ -435,17 +436,17 @@ public class JavacSingularsRecipes {
} catch (Exception e) {
inner = genJavaLangTypeRef(node, "Object");
}
- arguments.append(cloneType(maker, inner, source, context));
+ arguments.append(cloneType(maker, inner, source));
} else {
- arguments.append(cloneType(maker, orig, source, context));
+ arguments.append(cloneType(maker, orig, source));
}
} else {
if (orig.getKind() == Kind.UNBOUNDED_WILDCARD || orig.getKind() == Kind.SUPER_WILDCARD) {
arguments.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
} else if (orig.getKind() == Kind.EXTENDS_WILDCARD) {
- arguments.append(cloneType(maker, orig, source, context));
+ arguments.append(cloneType(maker, orig, source));
} else {
- arguments.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), cloneType(maker, orig, source, context)));
+ arguments.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), cloneType(maker, orig, source)));
}
}
if (--count == 0) break;
@@ -468,7 +469,7 @@ public class JavacSingularsRecipes {
JCExpression fn = maker.Select(maker.Select(maker.Ident(thisName), name), builderType.toName("size"));
JCExpression sizeInvoke = maker.Apply(List.<JCExpression>nil(), fn, List.<JCExpression>nil());
if (nullGuard) {
- JCExpression isNull = maker.Binary(CTC_EQUAL, maker.Select(maker.Ident(thisName), name), maker.Literal(CTC_BOT, 0));
+ JCExpression isNull = maker.Binary(CTC_EQUAL, maker.Select(maker.Ident(thisName), name), maker.Literal(CTC_BOT, null));
JCExpression out = maker.Conditional(isNull, maker.Literal(CTC_INT, 0), sizeInvoke);
if (parens) return maker.Parens(out);
return out;
@@ -476,7 +477,7 @@ public class JavacSingularsRecipes {
return sizeInvoke;
}
- protected JCExpression cloneParamType(int index, JavacTreeMaker maker, List<JCExpression> typeArgs, JavacNode builderType, JCTree source) {
+ protected JCExpression cloneParamType(int index, JavacTreeMaker maker, List<JCExpression> typeArgs, JavacNode builderType, JavacNode source) {
if (typeArgs == null || typeArgs.size() <= index) {
return genJavaLangTypeRef(builderType, "Object");
} else {
@@ -485,12 +486,12 @@ public class JavacSingularsRecipes {
return genJavaLangTypeRef(builderType, "Object");
} else if (originalType.getKind() == Kind.EXTENDS_WILDCARD) {
try {
- return cloneType(maker, (JCExpression) ((JCWildcard) originalType).inner, source, builderType.getContext());
+ return cloneType(maker, (JCExpression) ((JCWildcard) originalType).inner, source);
} catch (Exception e) {
return genJavaLangTypeRef(builderType, "Object");
}
} else {
- return cloneType(maker, originalType, source, builderType.getContext());
+ return cloneType(maker, originalType, source);
}
}
}
@@ -500,5 +501,11 @@ public class JavacSingularsRecipes {
protected abstract int getTypeArgumentsCount();
protected abstract String getEmptyMaker(String target);
+
+ public JCExpression getEmptyExpression(String target, JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
+ String emptyMaker = getEmptyMaker(target);
+ List<JCExpression> typeArgs = createTypeArgs(getTypeArgumentsCount(), false, builderType, data.getTypeArgs(), source);
+ return maker.Apply(typeArgs, chainDots(builderType, emptyMaker.split("\\.")), List.<JCExpression>nil());
+ }
}
}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java
index e0621cf7..84840799 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-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,10 +23,9 @@ package lombok.javac.handlers.singulars;
import lombok.core.LombokImmutableList;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.spi.Provides;
-import org.mangosdk.spi.ProviderFor;
-
-@ProviderFor(JavacSingularizer.class)
+@Provides(JavacSingularizer.class)
public class JavacGuavaMapSingularizer extends JavacGuavaSingularizer {
// TODO cgcc.ImmutableMultimap, cgcc.ImmutableListMultimap, cgcc.ImmutableSetMultimap
// TODO cgcc.ImmutableClassToInstanceMap
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java
index 5c7fcab5..44d6d15b 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,12 +21,11 @@
*/
package lombok.javac.handlers.singulars;
-import org.mangosdk.spi.ProviderFor;
-
import lombok.core.LombokImmutableList;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.spi.Provides;
-@ProviderFor(JavacSingularizer.class)
+@Provides(JavacSingularizer.class)
public class JavacGuavaSetListSingularizer extends JavacGuavaSingularizer {
// TODO com.google.common.collect.ImmutableRangeSet
// TODO com.google.common.collect.ImmutableMultiset and com.google.common.collect.ImmutableSortedMultiset
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
index 7cd676c0..ce5aad5e 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
@@ -39,7 +39,6 @@ import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
@@ -62,7 +61,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
return "builder";
}
- @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
+ @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JavacNode source) {
JavacTreeMaker maker = builderType.getTreeMaker();
String simpleTypeName = getSimpleTargetTypeName(data);
JCExpression type = JavacHandlerUtil.chainDots(builderType, "com", "google", "common", "collect", simpleTypeName, "Builder");
@@ -72,7 +71,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JavacNode source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
doGenerateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
}
@@ -83,7 +82,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
}
@Override
- protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
Name[] names = generateSingularMethodParameterNames(data, builderType);
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
for (int i = 0; i < names.length; i++) {
@@ -93,7 +92,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
}
@Override
- protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
Name[] names = generateSingularMethodParameterNames(data, builderType);
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName());
@@ -124,7 +123,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
return genTypeRef(builderType, getAddAllTypeName());
}
- @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JavacNode source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
JavacTreeMaker maker = builderType.getTreeMaker();
List<JCExpression> jceBlank = List.nil();
@@ -151,12 +150,12 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
JCExpression init = maker.Conditional(isNull, empty, invokeBuild); // this.pluralName == null ? ImmutableX.of() : this.pluralName.build()
- JCStatement jcs = maker.VarDef(maker.Modifiers(0), data.getPluralName(), varType, init);
+ JCStatement jcs = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), varType, init);
statements.append(jcs);
}
@Override
- protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
List<JCExpression> jceBlank = List.nil();
JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName());
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java
index 080266b8..bdc5facc 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,12 +21,11 @@
*/
package lombok.javac.handlers.singulars;
-import org.mangosdk.spi.ProviderFor;
-
import lombok.core.LombokImmutableList;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.spi.Provides;
-@ProviderFor(JavacSingularizer.class)
+@Provides(JavacSingularizer.class)
public class JavacGuavaTableSingularizer extends JavacGuavaSingularizer {
private static final LombokImmutableList<String> SUFFIXES =
LombokImmutableList.of("rowKey", "columnKey", "value");
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
index 634a086d..dfc8c7b0 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
@@ -37,7 +37,6 @@ import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
@@ -58,7 +57,7 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
return super.listMethodsToBeGenerated(data, builderType);
}
- @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
+ @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JavacNode source) {
JavacTreeMaker maker = builderType.getTreeMaker();
JCExpression type = JavacHandlerUtil.chainDots(builderType, "java", "util", "ArrayList");
type = addTypeArgs(1, false, builderType, type, data.getTypeArgs(), source);
@@ -67,7 +66,7 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JavacNode source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
doGenerateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
}
@@ -84,13 +83,13 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
}
@Override
- protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
return new ListBuffer<JCStatement>()
.append(generateSingularMethodAddStatement(maker, builderType, data.getSingularName(), data.getPluralName().toString()));
}
@Override
- protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
JCVariableDecl param = generateSingularMethodParameter(0, maker, data, builderType, source, data.getSingularName());
return List.of(param);
}
@@ -101,7 +100,7 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
}
@Override
- protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
return createConstructBuilderVarIfNeeded(maker, data, builderType, false, source);
}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
index b4ad3428..10f1ddd1 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-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,15 +24,13 @@ package lombok.javac.handlers.singulars;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-import org.mangosdk.spi.ProviderFor;
-
import lombok.core.LombokImmutableList;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+import lombok.spi.Provides;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCase;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCStatement;
@@ -40,7 +38,7 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
-@ProviderFor(JavacSingularizer.class)
+@Provides(JavacSingularizer.class)
public class JavacJavaUtilListSingularizer extends JavacJavaUtilListSetSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.List", "java.util.Collection", "java.lang.Iterable");
@@ -50,7 +48,7 @@ public class JavacJavaUtilListSingularizer extends JavacJavaUtilListSetSingulari
return "java.util.Collections.emptyList";
}
- @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JavacNode source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
JavacTreeMaker maker = builderType.getTreeMaker();
List<JCExpression> jceBlank = List.nil();
ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
@@ -89,12 +87,12 @@ public class JavacJavaUtilListSingularizer extends JavacJavaUtilListSetSingulari
JCStatement switchStat = maker.Switch(getSize(maker, builderType, data.getPluralName(), true, false, builderVariable), cases.toList());
JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
localShadowerType = addTypeArgs(1, false, builderType, localShadowerType, data.getTypeArgs(), source);
- JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null);
+ JCStatement varDefStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, null);
statements.append(varDefStat);
statements.append(switchStat);
}
- private List<JCStatement> createListCopy(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, String builderVariable) {
+ private List<JCStatement> createListCopy(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source, String builderVariable) {
List<JCExpression> jceBlank = List.nil();
Name thisName = builderType.toName(builderVariable);
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
index 8dc7ecff..b8c931c7 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2019 The Project Lombok Authors.
+ * Copyright (C) 2015-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
@@ -36,11 +36,9 @@ import lombok.javac.handlers.JavacSingularsRecipes.ExpressionMaker;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
import lombok.javac.handlers.JavacSingularsRecipes.StatementMaker;
-
-import org.mangosdk.spi.ProviderFor;
+import lombok.spi.Provides;
import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCStatement;
@@ -49,7 +47,7 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
-@ProviderFor(JavacSingularizer.class)
+@Provides(JavacSingularizer.class)
public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
@@ -74,7 +72,7 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
return super.listMethodsToBeGenerated(data, builderType);
}
- @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
+ @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JavacNode source) {
JavacTreeMaker maker = builderType.getTreeMaker();
JCVariableDecl buildKeyField; {
@@ -98,7 +96,7 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
return Arrays.asList(keyFieldNode, valueFieldNode);
}
- @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
+ @Override public void generateMethods(CheckerFrameworkVersion cfv, SingularData data, boolean deprecate, JavacNode builderType, JavacNode source, boolean fluent, ExpressionMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) {
doGenerateMethods(cfv, data, deprecate, builderType, source, fluent, returnTypeMaker, returnStatementMaker, access);
}
@@ -117,7 +115,7 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
}
@Override
- protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected ListBuffer<JCStatement> generateSingularMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
Name valueName = builderType.toName(data.getSingularName().toString() + "Value");
@@ -130,7 +128,7 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
}
@Override
- protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected List<JCVariableDecl> generateSingularMethodParameters(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
Name valueName = builderType.toName(data.getSingularName().toString() + "Value");
JCVariableDecl paramKey = generateSingularMethodParameter(0, maker, data, builderType, source, keyName);
@@ -139,7 +137,7 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
}
@Override
- protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
List<JCExpression> jceBlank = List.nil();
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
long baseFlags = JavacHandlerUtil.addFinalIfNeeded(0, builderType.getContext());
@@ -164,11 +162,11 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
}
@Override
- protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JavacNode source) {
return createConstructBuilderVarIfNeeded(maker, data, builderType, true, source);
}
- @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JavacNode source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
JavacTreeMaker maker = builderType.getTreeMaker();
if (data.getTargetFqn().equals("java.util.Map")) {
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java
index 7c870c0a..6d2e0655 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2021 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,20 +21,18 @@
*/
package lombok.javac.handlers.singulars;
-import org.mangosdk.spi.ProviderFor;
-
import lombok.core.LombokImmutableList;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+import lombok.spi.Provides;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
-@ProviderFor(JavacSingularizer.class)
+@Provides(JavacSingularizer.class)
public class JavacJavaUtilSetSingularizer extends JavacJavaUtilListSetSingularizer {
@Override public LombokImmutableList<String> getSupportedTypes() {
return LombokImmutableList.of("java.util.Set", "java.util.SortedSet", "java.util.NavigableSet");
@@ -46,7 +44,7 @@ public class JavacJavaUtilSetSingularizer extends JavacJavaUtilListSetSingulariz
return "java.util.Collections.emptySet";
}
- @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JavacNode source, ListBuffer<JCStatement> statements, Name targetVariableName, String builderVariable) {
JavacTreeMaker maker = builderType.getTreeMaker();
if (data.getTargetFqn().equals("java.util.Set")) {
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
index 50950915..3b6113df 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
@@ -24,7 +24,6 @@ package lombok.javac.handlers.singulars;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCase;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCStatement;
@@ -38,7 +37,7 @@ import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
- protected List<JCStatement> createJavaUtilSetMapInitialCapacitySwitchStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType, JCTree source, String builderVariable) {
+ protected List<JCStatement> createJavaUtilSetMapInitialCapacitySwitchStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType, JavacNode source, String builderVariable) {
List<JCExpression> jceBlank = List.nil();
ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
@@ -84,13 +83,13 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
JCStatement switchStat = maker.Switch(getSize(maker, builderType, mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName(), true, false, builderVariable), cases.toList());
JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source);
- JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null);
+ JCStatement varDefStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, null);
return List.of(varDefStat, switchStat);
}
- protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, JCTree source) {
+ protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, JavacNode source) {
List<JCExpression> jceBlank = List.nil();
-
+
Name v1Name = mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName();
Name v2Name = mapMode ? builderType.toName(data.getPluralName() + "$value") : null;
JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), v1Name);
@@ -117,7 +116,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
return maker.If(cond, thenPart, null);
}
- protected List<JCStatement> createJavaUtilSimpleCreationAndFillStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, boolean defineVar, boolean addInitialCapacityArg, boolean nullGuard, String targetType, JCTree source, String builderVariable) {
+ protected List<JCStatement> createJavaUtilSimpleCreationAndFillStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, boolean defineVar, boolean addInitialCapacityArg, boolean nullGuard, String targetType, JavacNode source, String builderVariable) {
List<JCExpression> jceBlank = List.nil();
Name thisName = builderType.toName(builderVariable);
@@ -143,7 +142,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
if (defineVar) {
JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source);
- createStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, constructorCall);
+ createStat = maker.VarDef(maker.Modifiers(0L), data.getPluralName(), localShadowerType, constructorCall);
} else {
createStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), constructorCall));
}
@@ -161,7 +160,7 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
// error: method put in interface Map<K#2,V#2> cannot be applied to given types;
arg2 = maker.TypeCast(createTypeArgs(2, false, builderType, data.getTypeArgs(), source).get(1), arg2);
JCStatement putStatement = maker.Exec(maker.Apply(jceBlank, pluralnameDotPut, List.of(arg1, arg2)));
- JCStatement forInit = maker.VarDef(maker.Modifiers(0), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0));
+ JCStatement forInit = maker.VarDef(maker.Modifiers(0L), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0));
JCExpression checkExpr = maker.Binary(CTC_LESS_THAN, maker.Ident(ivar), getSize(maker, builderType, keyVarName, nullGuard, true, builderVariable));
JCExpression incrementExpr = maker.Unary(CTC_POSTINC, maker.Ident(ivar));
fillStat = maker.ForLoop(List.of(forInit), checkExpr, List.of(maker.Exec(incrementExpr)), putStatement);