Skip to content

Commit

Permalink
add support for ProcessingEnvironments provided by IntelliJ and Gradle
Browse files Browse the repository at this point in the history
  • Loading branch information
mtf90 committed Jan 17, 2024
1 parent 2a575e2 commit f6d3afa
Showing 1 changed file with 69 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
package de.learnlib.tooling.processor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
Expand Down Expand Up @@ -65,7 +69,10 @@ public void init(ProcessingEnvironment processingEnv) {
this.messager = super.processingEnv.getMessager();
this.typeUtils = super.processingEnv.getTypeUtils();
this.elementUtils = super.processingEnv.getElementUtils();
this.docUtils = DocTrees.instance(processingEnv);

// DocTrees expects a com.sun.tools.javac.processing.JavacProcessingEnvironment
final ProcessingEnvironment unwrappedEnv = unwrapProcessingEnvironment(processingEnv);
this.docUtils = DocTrees.instance(unwrappedEnv);
}

protected void printError(String msg, Element element) {
Expand Down Expand Up @@ -137,7 +144,8 @@ protected void addReferentialDocumentation(ExecutableElement e,
docBuilder.add(paramBuilder.build());

for (TypeMirror thrownType : e.getThrownTypes()) {
docBuilder.add("@throws $T if the call to the delegate throws this exception\n", TypeName.get(thrownType));
docBuilder.add("@throws $T if the call to the delegate throws this exception\n",
TypeName.get(thrownType));
}

consumer.accept(docBuilder.build());
Expand Down Expand Up @@ -195,4 +203,63 @@ private boolean requiresSafeVarargs(TypeName type) {
return false;
}
}

/*
* Work around non-javac-native ProcessingEnvironments that are provided by some build environments but incompatible
* with (supposedly non-) internal Java APIs.
*
* Based on https://youtrack.jetbrains.com/issue/IDEA-274697/java-java.lang.IllegalArgumentException and
* https://github.com/typetools/checker-framework/pull/4082
*/
private ProcessingEnvironment unwrapProcessingEnvironment(ProcessingEnvironment env) {
if ("com.sun.tools.javac.processing.JavacProcessingEnvironment".equals(env.getClass().getName())) {
return env;
}
// IntelliJ >2020.3 wraps the processing environment in a dynamic proxy.
final ProcessingEnvironment unwrappedIntelliJ = unwrapIntelliJ(env);
if (unwrappedIntelliJ != null) {
return unwrapProcessingEnvironment(unwrappedIntelliJ);
}
// Gradle incremental build also wraps the processing environment.
for (Class<?> envClass = env.getClass(); envClass != null; envClass = envClass.getSuperclass()) {
final ProcessingEnvironment unwrappedGradle = unwrapGradle(envClass, env);
if (unwrappedGradle != null) {
return unwrapProcessingEnvironment(unwrappedGradle);
}
}
messager.printMessage(Kind.ERROR, "Cannot handle processing environment: " + env);
return env;
}

private ProcessingEnvironment unwrapIntelliJ(ProcessingEnvironment env) {
if (Proxy.isProxyClass(env.getClass())) {
try {
@SuppressWarnings("PMD.UseProperClassLoader") // we're not in an J2EE context and need the CL of env
final Class<?> wrappers =
env.getClass().getClassLoader().loadClass("org.jetbrains.jps.javac.APIWrappers");
final Method unwrapMethod = wrappers.getDeclaredMethod("unwrap", Class.class, Object.class);
return (ProcessingEnvironment) unwrapMethod.invoke(null, ProcessingEnvironment.class, env);
} catch (IllegalAccessException | ClassNotFoundException | InvocationTargetException |
NoSuchMethodException ignored) {
// do nothing
}
}

return null;
}

private static ProcessingEnvironment unwrapGradle(Class<?> delegateClass, ProcessingEnvironment env) {
try {
final Field field = delegateClass.getDeclaredField("delegate");
field.setAccessible(true);
final Object o = field.get(env);
if (o instanceof ProcessingEnvironment) {
return (ProcessingEnvironment) o;
}
} catch (NoSuchFieldException | IllegalAccessException ignored) {
// do nothing
}

return null;
}
}

0 comments on commit f6d3afa

Please sign in to comment.