custom intention to import class in injected language
Hi!
My EXML plugin (sources in this git repo) uses a special XML format (much like MXML) that contains inline ActionScript code. I managed to set up language injection to do syntax highlighting and completion correctly, but I would like the "import class" intention to be handled differently. Currently, the import statement is inserted directly at the start of the code fragment, but in EXML, imports are supposed to be top-level XML elements.
I'm a bit lost where to start. The Flex plugin must handle MXML in a similar way, so there must be a way to do this.
Any hint / pointer would be appreciated!
Greetings,
-Frank-
请先登录再写评论。
Okay, so please does anyone have any general hints where to start if I want to implement a custom "intention" action, i.e. influence what happens when you press Alt+Return? Especially example code would be very helpful!
In your initComponent:
...where MyIntentionAction is an instance of IntentionAction (see its javadoc for more information).
Hello Ronnie,
Please do not do this in initComponent(). Use the extension
point instead.
--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"
You are of course right about this :) I sometines use initComponent and often projectOpened (for easily hot-swapping the sandbox) when prototyping various things.
The correct way is to register the intention action by using the extension point com.intellij.intentionAction in your plugin.xml.
I just checked the Flex plugin, and instead of intentionAction, it uses the extension point com.intellij.referenceImporter, which in turn instantiates and executes an IntentionAction.
I tried to implement a custom referenceImporter, but it seems my class is not even loaded (no debugging possible, no check mark in red dot).
...where ExmlReferenceImporter implements com.intellij.codeInsight.daemon.ReferenceImporter. The only method, autoImportReferenceAtCursor, is never called.
I could not find any documentation of this feature, can anyone help out?
Like several others in this forum who develop plugins with IDEA 10.0.2, I also see the following exception (not sure if it has anything to do with my problem):
ERROR: gnu/trove/THashSet
java.lang.NoClassDefFoundError: gnu/trove/THashSet
at com.intellij.openapi.util.Disposer.<clinit>(Disposer.java:33)
at com.intellij.util.Timed.disposeTimed(Timed.java:96)
at com.intellij.util.Timed$1.run(Timed.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:181)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:205)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.ClassNotFoundException: gnu.trove.THashSet
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 12 more
Hello Frank,
This is not "instead". The referenceImporter is used in very specific cases,
such as trying to invoke completion when the reference before the caret is
unresolved. The actual auto-import is implemented by registering a quickfix
for the unresolved reference inspection. I don't think this is pluggable
for Flex, however, you still can use IntentionAction to perform auto-import
in your case.
Note that you can find complete information on how the referenceImporter
is used in the CE source code.
--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"
Thanks Dmitry,
okay, I think I'm beginning to understand. I managed to implement a custom IntentionAction that actually gets called.
However, what I want to achieve is very similar to com.intellij.lang.javascript.flex.AddImportECMAScriptClassOrFunctionAction. I managed to identify this class to provide the (in case of EXML) wrong QuickFix.
EXML consists of XML containing ActionScript code fragments. Similar to MXML, classes used in these code fragments should be imported at the top of the containing XML file (using special XML elements). But AddImportECMAScriptClassOrFunctionAction inserts the import declaration directly at the beginning of the code fragment.
When looking at the method signature of AddImportECMAScriptClassOrFunctionAction's constructor, it receives two arguments (Editor and PsiPolyVariantReference). It seems this class is not registered through an extension point, as you describe, but constructed from code. So how can I tweak the behavior? How can my custom IntentionAction receive the same "context" to work on? I would like to reuse as much as possible, because only the actual manipulation of the code is different, everything else (show the hint, find and display suggestions, let the user select one) is the same!
One more thing: what about the com.intellij.codeInsight.unresolvedReferenceQuickFixProvider? Is this where you register custom com.intellij.codeInspection.QuickFix classes? Sounds like it could help in my use case, too...
-Frank-
I'm still stuck at this point, anyone who could help?
Hello Frank,
Your IntentionAction receives an Editor and a PsiFile as context. You can
use editor.getCaretModel().getCaretOffset() to find where the cart is, then
file.findReferenceAt() to find the reference.
At the moment this extension point is used only for unresolved references
in Java and XML. It could be used for ActionScript as well, but right now
it's not.
--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"