From a2623f1965848cb941374f70ae008f56d7738736 Mon Sep 17 00:00:00 2001 From: Pascal Bihler Date: Thu, 3 May 2018 11:57:01 +0200 Subject: Allow gradle incremental compiling with lombok in annotation processor path Fixes issue #1580 --- src/core/lombok/core/AnnotationProcessor.java | 30 ++++++++- src/core/lombok/javac/apt/LombokProcessor.java | 84 ++++++++++++++++++++------ 2 files changed, 93 insertions(+), 21 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java index 5b4ef393..d05597b6 100644 --- a/src/core/lombok/core/AnnotationProcessor.java +++ b/src/core/lombok/core/AnnotationProcessor.java @@ -26,6 +26,7 @@ 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.Method; import java.net.URL; import java.util.ArrayList; @@ -63,6 +64,27 @@ public class AnnotationProcessor extends AbstractProcessor { private final List registered = Arrays.asList(new JavacDescriptor(), new EcjDescriptor()); private final List active = new ArrayList(); private final List delayedWarnings = new ArrayList(); + + /** + * 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. + */ + public static ProcessingEnvironment getJavacProcessingEnvironment(ProcessingEnvironment procEnv, List delayedWarnings) { + final Class procEnvClass = procEnv.getClass(); + if (procEnvClass.getName().equals("org.gradle.api.internal.tasks.compile.processing.IncrementalProcessingEnvironment")) { + try { + Field field = procEnvClass.getDeclaredField("delegate"); + field.setAccessible(true); + Object delegate = field.get(procEnv); + return (ProcessingEnvironment) delegate; + } catch (final Exception e) { + delayedWarnings.add("Can't get the delegate of the gradle IncrementalProcessingEnvironment: " + trace(e)); + } + } + return procEnv; + } + static class JavacDescriptor extends ProcessorDescriptor { private Processor processor; @@ -72,10 +94,12 @@ public class AnnotationProcessor extends AbstractProcessor { } @Override boolean want(ProcessingEnvironment procEnv, List delayedWarnings) { - if (!procEnv.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) return false; - + ProcessingEnvironment javacProcEnv = getJavacProcessingEnvironment(procEnv, delayedWarnings); + + if (!javacProcEnv.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) return false; + try { - ClassLoader classLoader = findAndPatchClassLoader(procEnv); + ClassLoader classLoader = findAndPatchClassLoader(javacProcEnv); processor = (Processor) Class.forName("lombok.javac.apt.LombokProcessor", false, classLoader).newInstance(); } catch (Exception e) { delayedWarnings.add("You found a bug in lombok; lombok.javac.apt.LombokProcessor is not available. Lombok will not run during this compilation: " + trace(e)); diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java index 9c0a2dfa..fc457735 100644 --- a/src/core/lombok/javac/apt/LombokProcessor.java +++ b/src/core/lombok/javac/apt/LombokProcessor.java @@ -37,6 +37,7 @@ import java.util.Set; import java.util.SortedSet; import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; @@ -69,7 +70,9 @@ import com.sun.tools.javac.util.Context; */ @SupportedAnnotationTypes("*") public class LombokProcessor extends AbstractProcessor { - private JavacProcessingEnvironment processingEnv; + private ProcessingEnvironment processingEnv; + private JavacProcessingEnvironment javacProcessingEnv; + private JavacFiler javacFiler; private JavacTransformer transformer; private Trees trees; private boolean lombokDisabled = false; @@ -81,11 +84,13 @@ public class LombokProcessor extends AbstractProcessor { lombokDisabled = true; return; } - - this.processingEnv = (JavacProcessingEnvironment) procEnv; - + + this.processingEnv = procEnv; + this.javacProcessingEnv = getJavacProcessingEnvironment(procEnv); + this.javacFiler = getJavacFiler(procEnv.getFiler()); + placePostCompileAndDontMakeForceRoundDummiesHook(); - trees = Trees.instance(procEnv); + trees = Trees.instance(javacProcessingEnv); transformer = new JavacTransformer(procEnv.getMessager(), trees); SortedSet p = transformer.getPriorities(); if (p.isEmpty()) { @@ -124,7 +129,7 @@ public class LombokProcessor extends AbstractProcessor { @SuppressWarnings("unused") private String listAnnotationProcessorsBeforeOurs() { try { - Object discoveredProcessors = javacProcessingEnvironment_discoveredProcs.get(this.processingEnv); + Object discoveredProcessors = javacProcessingEnvironment_discoveredProcs.get(this.javacProcessingEnv); ArrayList states = (ArrayList) discoveredProcessors_procStateList.get(discoveredProcessors); if (states == null || states.isEmpty()) return null; if (states.size() == 1) return processorState_processor.get(states.get(0)).getClass().getName(); @@ -147,7 +152,7 @@ public class LombokProcessor extends AbstractProcessor { stopJavacProcessingEnvironmentFromClosingOurClassloader(); forceMultipleRoundsInNetBeansEditor(); - Context context = processingEnv.getContext(); + Context context = javacProcessingEnv.getContext(); disablePartialReparseInNetBeansEditor(context); try { Method keyMethod = Context.class.getDeclaredMethod("key", Class.class); @@ -161,14 +166,14 @@ public class LombokProcessor extends AbstractProcessor { if (!(originalFiler instanceof InterceptingJavaFileManager)) { final Messager messager = processingEnv.getMessager(); DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager); - - JavaFileManager newFiler = new InterceptingJavaFileManager(originalFiler, receiver); - ht.put(key, newFiler); + + JavaFileManager newFilerManager = new InterceptingJavaFileManager(originalFiler, receiver); + ht.put(key, newFilerManager); Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager"); filerFileManagerField.setAccessible(true); - filerFileManagerField.set(processingEnv.getFiler(), newFiler); - - replaceFileManagerJdk9(context, newFiler); + filerFileManagerField.set(javacFiler, newFilerManager); + + replaceFileManagerJdk9(context, newFilerManager); } } catch (Exception e) { throw Lombok.sneakyThrow(e); @@ -203,7 +208,7 @@ public class LombokProcessor extends AbstractProcessor { try { Field f = JavacProcessingEnvironment.class.getDeclaredField("isBackgroundCompilation"); f.setAccessible(true); - f.set(processingEnv, true); + f.set(javacProcessingEnv, true); } catch (NoSuchFieldException e) { // only NetBeans has it } catch (Throwable t) { @@ -277,10 +282,10 @@ public class LombokProcessor extends AbstractProcessor { try { Field f = JavacProcessingEnvironment.class.getDeclaredField("processorClassLoader"); f.setAccessible(true); - ClassLoader unwrapped = (ClassLoader) f.get(processingEnv); + ClassLoader unwrapped = (ClassLoader) f.get(javacProcessingEnv); if (unwrapped == null) return; ClassLoader wrapped = wrapClassLoader(unwrapped); - f.set(processingEnv, wrapped); + f.set(javacProcessingEnv, wrapped); } catch (NoSuchFieldException e) { // Some versions of javac have this (and call close on it), some don't. I guess this one doesn't have it. } catch (Throwable t) { @@ -321,7 +326,7 @@ public class LombokProcessor extends AbstractProcessor { if (prioOfCu == null || prioOfCu != prio) continue; cusForThisRound.add(entry.getKey()); } - transformer.transform(prio, processingEnv.getContext(), cusForThisRound); + transformer.transform(prio, javacProcessingEnv.getContext(), cusForThisRound); } // Step 3: Push up all CUs to the next level. Set level to null if there is no next level. @@ -349,7 +354,7 @@ public class LombokProcessor extends AbstractProcessor { newLevels.retainAll(priorityLevelsRequiringResolutionReset); if (!newLevels.isEmpty()) { // Force a new round to reset resolution. The next round will cause this method (process) to be called again. - forceNewRound(randomModuleName, (JavacFiler) processingEnv.getFiler()); + forceNewRound(randomModuleName, javacFiler); return false; } // None of the new levels need resolution, so just keep going. @@ -399,4 +404,47 @@ public class LombokProcessor extends AbstractProcessor { @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latest(); } + + /** + * This class casts the given processing environment to a JavacProcessingEnvironment. In case of + * gradle incremental compilation, the delegate ProcessingEnvironment of the gradle wrapper is returned. + */ + public JavacProcessingEnvironment getJavacProcessingEnvironment(ProcessingEnvironment procEnv) { + final Class procEnvClass = procEnv.getClass(); + if (procEnv.getClass().getName().equals("org.gradle.api.internal.tasks.compile.processing.IncrementalProcessingEnvironment")) { + try { + Field field = procEnvClass.getDeclaredField("delegate"); + field.setAccessible(true); + Object delegate = field.get(procEnv); + return (JavacProcessingEnvironment) delegate; + } catch (final Exception e) { + e.printStackTrace(); + procEnv.getMessager().printMessage(Kind.WARNING, + "Can't get the delegate of the gradle IncrementalProcessingEnvironment. Lombok won't work."); + } + } + return (JavacProcessingEnvironment) procEnv; + } + + /** + * This class casts the given filer to a JavacFiler. In case of + * gradle incremental compilation, the delegate Filer of the gradle wrapper is returned. + */ + public JavacFiler getJavacFiler(Filer filer) { + final Class filerSuperClass = filer.getClass().getSuperclass(); + if (filerSuperClass.getName().equals("org.gradle.api.internal.tasks.compile.processing.IncrementalFiler")) { + try { + Field field = filerSuperClass.getDeclaredField("delegate"); + field.setAccessible(true); + Object delegate = field.get(filer); + return (JavacFiler) delegate; + } catch (final Exception e) { + e.printStackTrace(); + processingEnv.getMessager().printMessage(Kind.WARNING, + "Can't get the delegate of the gradle IncrementalFiler. Lombok won't work."); + } + } + return (JavacFiler) filer; + } + } -- cgit