Use javac API in plugin

Answered

I want to run custom AnnotationProcessor from the plugin and I've found that javac API can be invoked easily from the java code itself. Like

compiler = ToolProvider.getSystemJavaCompiler();
...
task.setProcessors(Collections.singleton(p));

However, when I tried to invoke it from the Intellij Plugin, there was this error

> Error: Unable to find package java.lang in classpath or bootclasspath

I have correct jre setup, and I can build and compile my project from the IntelliJ. So I can't see why the classpath is incorrect.

 

Things that didn't help

Using another class loader to load compiler class

ClassLoader.getSystemClassLoader();
Object compiler = callStaticMethod(classLoader, JavacTool.class, "create");

Adding compiler options to the compilation task

String root = "/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home";
final List<String> options = Arrays.asList(
"-Xbootclasspath/p:" + root,
"-classpath", root);
JavaCompiler.CompilationTask task = compiler.getTask(outWriter, fileManager, diagnostics, options, Collections.singleton(qualifiedName), Collections.singleton(source));

Adding url to the UrlClassLoader before calling compiler

String pathname = "/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/rt.jar";
File pathElement = new File(pathname);
URL url = pathElement.toPath().normalize().toUri().toURL();
callInstanceMethod(urlClassLoader, "addURL", new Class[]{URL.class}, url);

I'm still seeing this error "Unable to find package java.lang in classpath or bootclasspath" 

Anyone has ideas how to configure plugin to run javac API?

1
6 comments

Please explain in more detail, what "run custom AnnotationProcessor from the plugin" means exactly

- how is this related to IJ plugin

- what code is instrumented

- what is triggering it

0

Yann Cebron I've attached a sample project to showcase idea

>>>> file <<<<

root

-- comp (Java module)

---- MyProcessor.java (AnnotationProcessor I try getting invoked)

---- Formatter.java (file retrieving and calling javac from the code)

-- ide (IJ module)

---- ParseAction (IJ action get called by the user)

 

When a user clicks "ParseAction" from the Editor menu, it calls Formatter. 

Expected: AnnotationProcessor is triggered

Actual: error "Unable to find package java.lang in classpath or bootclasspath" is written during task#call

I've been struggling with this blocker for a few weeks already, trying different combinations (mentioned in the question). It would be amazing if you can see the root of a problem and help me fix it.

0

My guess this is because "comp" module classes are loaded with `UriClassLoader`. But I don't see a way to change it: even when other class loader is set per thread, javac classes are still loaded with `UriClassLoader`.

0

Sergey I see you had similar project long time in the past, maybe you can help?

0

Did you try any of the given workaround from the other thread?

0

Yes, actually, I changed the calling class to enum, removed custom Context and DiagnosticCollector, and change FileManger implementation, and it worked in the end. Not sure what exactly helped..

0

Please sign in to leave a comment.