dkandalov / live-plugin

IntelliJ plugin for writing IntelliJ plugins at runtime ⚡️
https://plugins.jetbrains.com/plugin/7282
Apache License 2.0
818 stars 66 forks source link

Groovy plugin script cannot resolve IntelliJ and Live Plugin API classes #175

Open kriegaex opened 3 months ago

kriegaex commented 3 months ago

I just installed the plugin for the first time in IDEA 2023.3.6 Ultimate and opened the Groovy "hello world" example. I can successfully run the plugin, but in the editor it looks like this:

image

Is there anything else I need to configure?

kriegaex commented 3 months ago

It seems as if this helps:

image

But unfortunately, I have literally hundreds of projects in my workspace. Furthermore, whenever e.g. Maven is the leading build tool, each automatic or manual re-import resets the dependencies, i.e. I have to start over and re-add the IDE and plugin libraries over and over.

Please advise me how to set this up in a better and more persistent way. Thank you. P.S.: I do not speak Kotlin, which is the reason why I chose Groovy.

dkandalov commented 3 months ago

Is there anything else I need to configure?

Not really. Groovy highlighting in the editor has always been a bit of a hack to make a point that it would be nice to have it. It seems like there are APIs in IntelliJ to achieve that but I never got around to figuring it out how to do that for Groovy (and I switched to using Kotlin a few years ago).

You could create a separate project for your live plugin with all the dependencies and it will have syntax highlighting 🤔 Each live plugin is just a folder and you can find the path with the copy path action ctrl+shift+c in the tool window or in the "Project view -> Scratches and Consoles -> Live Plugins".

Or once the plugin becomes more established I sometimes create a "proper plugin" project with plugin.xml but still keep it reloadable via live plugin for faster feedback by adding plugin jar to live plugin classpath (https://github.com/dkandalov/live-plugin/blob/master/plugin-examples/groovy/additional-classpath/plugin.groovy).

These suggestions break the promise of minimal setup for live plugins though 😕

kriegaex commented 3 months ago

adding plugin jar to live plugin classpath (https://github.com/dkandalov/live-plugin/blob/master/plugin-examples/groovy/additional-classpath/plugin.groovy).

Well, there is the next problem. Globbing does not work as advertised. This fails:

// add-to-classpath $HOME/.m2/repository/org/mockito/mockito-core/3.3.3/mockito*.jar

I only got the plugin working with the full path:

// add-to-classpath $HOME/.m2/repository/org/mockito/mockito-core/3.3.3/mockito-core-3.3.3.jar
kriegaex commented 3 months ago

Another issue is that the imports do not seem to work. I wanted to convert this Kotlin live plugin to Groovy and extend it, but some plugin classes are not found:

image

Besides, the corresponding compilation stack trace with butchered line breaks is also not super beautiful:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:file:/C:/Users/alexa/AppData/Roaming/JetBrains/IntelliJIdea2023.3/live-plugins/AJ-Maven-post-compile/plugin.groovy: 9: unable to resolve class liveplugin.PluginUtil.showInConsole @ line 9, column 1.   import liveplugin.PluginUtil.showInConsole   ^file:/C:/Users/alexa/AppData/Roaming/JetBrains/IntelliJIdea2023.3/live-plugins/AJ-Maven-post-compile/plugin.groovy: 10: unable to resolve class liveplugin.show @ line 10, column 1.   import liveplugin.show   ^file:/C:/Users/alexa/AppData/Roaming/JetBrains/IntelliJIdea2023.3/live-plugins/AJ-Maven-post-compile/plugin.groovy: 11: unable to resolve class liveplugin.whenDisposed @ line 11, column 1.   import liveplugin.whenDisposed   ^3 errors
    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:292)
    at org.codehaus.groovy.control.CompilationUnit$ISourceUnitOperation.doPhaseOperation(CompilationUnit.java:915)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:628)
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:389)
    at groovy.lang.GroovyClassLoader.lambda$parseClass$3(GroovyClassLoader.java:332)
    at org.codehaus.groovy.runtime.memoize.StampedCommonCache.compute(StampedCommonCache.java:163)
    at org.codehaus.groovy.runtime.memoize.StampedCommonCache.getAndPut(StampedCommonCache.java:154)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:330)
    at groovy.util.GroovyScriptEngine$ScriptClassLoader.doParseClass(GroovyScriptEngine.java:232)
    at groovy.util.GroovyScriptEngine$ScriptClassLoader.parseClass(GroovyScriptEngine.java:219)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:314)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:257)
    at groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:529)
    at liveplugin.implementation.pluginrunner.groovy.GroovyPluginRunner.setup(GroovyPluginRunner.kt:54)
    at liveplugin.implementation.pluginrunner.PluginRunnerKt$runWith$1.invoke(PluginRunner.kt:161)
    at liveplugin.implementation.pluginrunner.PluginRunnerKt$runInBackground$2.run(PluginRunner.kt:176)

P.S.: If you want separate issues for each of these problems, I understand. I was just in the middle of writing my first Groovy plugin, and all the mentioned problems are occurring in the same context, even though they are of course logically separate. And sorry again for not being a Kotlin person. I am sure, it would be worth the time to learn that interesting language. But not just for this plugin.

dkandalov commented 3 months ago

Hm, this works fine for me, maybe it's broken on Windows 🤦

// add-to-classpath $HOME/.m2/repository/org/mockito/mockito-core/5.7.0/mockito*.jar
show(org.mockito.Mockito.class.name)

Agreed about butchered line breaks.

Looking at the errors:

I would approach converting Kotlin plugin to Groovy by rewriting it in small incremental steps.

I didn't really think about the case of converting Kotlin live plugin to Groovy 🤔 No problem not using Kotlin 😅 Initially, LivePlugin was Groovy only (because Kotlin didn't exist). But now IntelliJ is being converted to Kotlin anyway so it seems more logical to use it.

Ideally, LivePlugin APIs would be the same or very similar in both Groovy and Kotlin, but the Groovy one was first and I learned few things since then. Besides, LivePlugin API is a small wrapper around IntelliJ APIs which is quite big so it's impossible to cover it all and maintain it. The end goal would be to convince Jetbrains to maintain nice to use reloadable APIs (and some of them are!).

kriegaex commented 3 months ago

Hm, this works fine for me, maybe it's broken on Windows 🤦

Only, if you used platform-specific tools for implementing it, such as shell scripts.

I would approach converting Kotlin plugin to Groovy by rewriting it in small incremental steps.

Of course, this is exactly what I started to do. But it already failed at the very first step, importing classes from other plugins and resolving them, without even any active plugin code. Not knowing Kotlin, I did not notice that there obviously you do not need static for importing methods, so it did not occur to me that after copy & paste I would need to change that in Groovy. Now I know, thanks. I got the plugin and some of my own changes running. 😊

Ideally, LivePlugin APIs would be the same or very similar in both Groovy and Kotlin, but the Groovy one was first and I learned few things since then.

Does that mean, Groovy support remains as-is and you are hinting me at switching to Kotlin, or are you going to adjust the Groovy part, making it comparable in its capabilities to the Kotlin ones?

kriegaex commented 3 months ago

Hm, something strange is happening. After starting the plugin, it does exactly what it is supposed to, but it also blocks part of the IDE, e.g. I can delete, but not enter any text in the editor anymore and also cannot close the IDE without killing the task. Other parts of the IDE remain functional.

Probably I have a silly miskate in the plugin code, but what could it be? Even unloading the plugin does not unblock the IDE.

Edit: Forget about it, it must have been something about nested Groovy closures and it after factoring out an anonymous subclass into a named inner class. I needed to be more explicit with naming and parametrising parameters. Why the previous code made the IDE block is another question, but at least I managed to fix it, and it is not about your Live Plugin as such. Sorry for the noise.

dkandalov commented 3 months ago

Does that mean, Groovy support remains as-is and you are hinting me at switching to Kotlin, or are you going to adjust the Groovy part, making it comparable in its capabilities to the Kotlin ones?

I wasn't hinting at switching to Kotlin 😅 Although my next plans for live plugin would be about integrating proper IDE runner, configurable compile and runtime classpaths, maybe built-in PSI viewer, object inspector, plugin reload while typing, etc. I haven't considered revisiting Groovy API, it's the first time anyone asked about it 🤔

kriegaex commented 3 months ago

Well, I love to write tests in Spock (or Geb, if they are web UI tests), therefore I know some Groovy. Using that language, I can get live plugin stuff done without learning a new language first. Comfort zone...

mikehearn commented 1 month ago

This isn't Groovy specific. I installed LivePlugin today and it fails in the same way for both Kotlin and Groovy. For some reason the class path of the plugin isn't correct for the editor. For running it works fine!

Clicking the "Add to project" menu item does not work to resolve this for some reason.

It might be a regression in IntelliJ. After restarting the IDE a "apply script context" bar appeared and clicking it fixed the highlighting.

dkandalov commented 1 month ago

@mikehearn What are the IDE and plugin versions? (because it works for me on two machines)

mikehearn commented 1 month ago

This is IJ Ultimate, latest version, and LivePlugin was installed from the marketplace yesterday. So presumably it's the latest version.