How to debug a BuilderService plugin
Hi all,
Using the information available at http://confluence.jetbrains.com/display/IDEADEV/External+Builder+API+and+Plugins I'm trying to writing a small plugin to instrument the .class files after compilation.
Following the information on the above page I've:
- put the code and META-INF in the jps-plugin dir
- created the org.jetbrains.jps.incremental.BuilderService file in META-INF/services and put the fqcn in it
- subclassed BuilderService with
-- createModuleLevelBuilders() returning a List containing an instance of my plugin as only element
-- getTargetTypes() returning a List containing JavaModuleBuildTargetType.ALL_TYPES
-- createBuilders() just calls super.createBuilders()
- the plugin extends ClassProcessingBuilder (using BuilderCategory.CLASS_INSTRUMENTER as category)
I used https://github.com/JetBrains/intellij-scala as an example but must be doing some differently I guess.
Maybe I'm missing something wrong here because when I launch "debugging project" from the plugin project I see my plugin (i.e. it is listed) but the plugin it is not working. So I started wondering whether an external builder can be debugged this way and more importantly how to go about it correctly. Any pointer would be much appreciated.
Best regards,
Johan
Please sign in to leave a comment.
Hi Johan,
I've updated topics you mentioned with the the information about debugging external build process.
Hope this helps,
Best regards,
Eugene.
Hi Eugene,
Many thanks, I'll give it a try hopefully later today.
Best regards,
Johan
Hi,
I found a few traces of my plugin in the log directory.
The remote debugging setup seems to work but it seems none of my breakpoints are met. Compilation proceeds and the debug session ends right away. This makes me think that my plugin is not loaded by the ServiceLoader(*). In my first post I tried to give a (somewhat cryptic) description of my directory layout. Is this correct.
* As a quick try I added some System.out.println() debugging in the ctor of my BuilderService subclass. But I can't find any trace of it either in idea.log for instance.
Additionally I noticed the <idea-system-directory>/plugins-sandbox/plugins directory. I contains the files for "my plugin" but I noticed the META-INF directory only contains the plugin.xml file and nothing else. Is that correct? Should the services directory not appear there too?
Regards,
Johan
Hello,
yes, the 'services' directory should be copied to META-INF directory. It seems that files in 'META-INF/services' weren't accepted by 'Resource
patterns' in File | Settings | Compiler so they weren't copied to the output directory. You can specify something like '!.form;!.java;!*.class' in
'Resource patterns' to ensure that all necessary files are copied.
--
Nikolay Chashnikov
Software Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
Hi Johan,
First, please make sure the contents of your META-INF dierctory with service declarations is copied to the output. This is about resource patterns configuration in your compiler settings
Eugene.
Hi,
Thanks to both of you guys! With your help that part of the problem is fixed. META-INF/services gets populated correctly now.
Unfortunately I did not get much further after that. No sign of my plugin in action.
So I've put a breakpoint in the ServiceLoader of the jdk at the point where the content of META-INF/services/XYZ is being read (parse() method). I used the remote debugging target/run and indeed during compilation the breakpoint works. So far so good. I've put a condition on the breakpont: service.getName().equals("org.jetbrains.jps.incremental.BuilderService") . This way I see which impl fqcn are being read. Well all but mine :'(
I can see which jars are inspected and I've seen plenty (talk about tedious ;) ). In the following order : jps-server, ui-designer-jps-plugin, intellilang-jps-plugin, groovy-jps-plugin, maven-jps-plugin and android-jps-plugin but never did I see the path to <idea-system-directory>/plugins-sandbox/plugins In fact when inspecting the classloader(s) used inside the ServiceLoader I noticed that <idea-system-directory>/plugins-sandbox/plugins is not in the list. Is there some class loader magic used later on perhaps. I'll paste the classpath used by the classloader below.
Anyway, the more I look the less I understand how it could/should work. Can it work using the plugin sandbox in combination with the ServiceLoader? The way I understand it now (I maybe very very wrong of course) I think not. Are there other things I could try to get a grip on my problem. Any suggestion welcome. I'm pretty stuck at this point, sorry.
Best regards,
Johan
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/asm4-all.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/jna-utils.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/idea_rt.jar, f
ile:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/log4j.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/annotations.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/nanoxml-2.2.3.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/jna.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/oromatcher.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/optimizedFileManager.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/jdom.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/util.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/netty-3.6.2.Final.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/picocontainer.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/jgoodies-forms.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/protobuf-2.4.1.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/forms_rt.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/ecj-4.2.1.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/idea.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/jps-server.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/resources_en.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/trove4j.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/lib/openapi.jar,
file:/C:/Program%20Files/Java/jdk1.6.0_35/lib/tools.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/ant/lib/ant-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/devkit/lib/jps/devkit-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/uiDesigner/lib/jps/ui-designer-jps-plugin.jar, file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/IntelliLang/lib/intellilang-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/Groovy/lib/groovy-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/eclipse/lib/eclipse-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/eclipse/lib/common-eclipse-util.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/maven/lib/maven-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/maven/lib/maven3/plexus-utils-2.0.6.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/jps/android-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/android-common.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/android-rt.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/sdklib.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/common.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/jarutils.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/androidprefs.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/android/lib/layoutlib_api.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/javaFX/lib/javaFX-jps-plugin.jar,
file:/C:/Program%20Files/JetBrains/IntelliJ%20IDEA%20Community%20Edition%2012.1/plugins/javaFX/lib/common-javaFX-plugin.jar]
Hello,
your jps-plugin module should be included to the classpath of the external build process in CompileServerClasspathManager. If you use a plugin run
configuration you need to add a dependency on jps-plugin module to the main plugin module.
--
Nikolay Chashnikov
Software Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
Hi Nikolay,
I'm afraid I can't quite follow when you mention "CompileServerClasspathManager".
When you mention adding the dependency: the project only has 1 module the one with the plugin. As such the plugin run config uses the classpath of that module. Is that what you mean? Should the output path of the module not appear in the classpath then? In the list I got hold of there were only the IJ jars and the plugin jars (those in the plugins dir I mean).
I wonder whether I should not create the zip for the plugin and install it for the ServiceLoader construction to work.
Regards,
Johan
Hello,
CompileServerClasspathManager is a class in IDEA sources which is used to compose classpath for the external build process
(https://github.com/JetBrains/intellij-community/blob/master/java/compiler/impl/src/com/intellij/compiler/server/impl/CompileServerClasspathManager.java).
You can debug it to check why your plugin isn't added to the classpath.
Probably you forget to register the plugin for the external build using compileServer.plugin extension in the plugin.xml file.
--
Nikolay Chashnikov
Software Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
Hello Nikolay,
Thanks a million, that was my problem. Now my plugin gets loaded, super.
If I may I'd like to suggest adding that to the page in confluence because it is far from obvious.
Now it's up to the next issues ;)
Best regards,
Johan