Get VirtualFile of selected text editor from a non-UI thread
Hi,
I'm quite new to intellij plugin development.
I am trying to get the selected file like this:
RobotFileManager.java: 110 | Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
RobotFileManager.java: 111 | VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(editor.getDocument());
But I am getting the following exception :
Access is allowed from event dispatch thread only.
Details: Current thread: Thread[JobScheduler FJ pool 0/4,6,main] 1479683740
Our dispatch thread:Thread[AWT-EventQueue-1 13.1.4#IU-135.1230, eap:false,6,main] 733847011
SystemEventQueueThread: Thread[AWT-EventQueue-1 13.1.4#IU-135.1230, eap:false,6,main] 733847011
java.lang.Throwable
at com.intellij.openapi.diagnostic.Logger.error(Logger.java:124)
at com.intellij.openapi.application.impl.ApplicationImpl.a(ApplicationImpl.java:1086)
at com.intellij.openapi.application.impl.ApplicationImpl.assertIsDispatchThread(ApplicationImpl.java:1074)
at com.intellij.openapi.wm.impl.FocusManagerImpl.p(FocusManagerImpl.java:1163)
at com.intellij.openapi.wm.impl.FocusManagerImpl.getFocusOwner(FocusManagerImpl.java:891)
at com.intellij.openapi.wm.impl.IdeFocusManagerImpl.getFocusOwner(IdeFocusManagerImpl.java:119)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl$2.run(FileEditorManagerImpl.java:202)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl.a(FileEditorManagerImpl.java:230)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl.getSplitters(FileEditorManagerImpl.java:1180)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl.getSelectedTextEditor(FileEditorManagerImpl.java:1127)
at com.millennialmedia.intellibot.psi.ref.RobotFileManager.findFile(RobotFileManager.java:110)
at com.millennialmedia.intellibot.psi.ref.RobotFileManager.findGlobalFile(RobotFileManager.java:89)
at com.millennialmedia.intellibot.psi.ref.RobotFileManager.findRobot(RobotFileManager.java:46)
at com.millennialmedia.intellibot.psi.ref.RobotArgumentReference.resolveResource(RobotArgumentReference.java:181)
at com.millennialmedia.intellibot.psi.ref.RobotArgumentReference.resolve(RobotArgumentReference.java:44)
at com.intellij.codeInsight.TargetElementUtilBase.getReferenceOrReferencedElement(TargetElementUtilBase.java:315)
at com.intellij.codeInsight.TargetElementUtil.getReferenceOrReferencedElement(TargetElementUtil.java:95)
at com.intellij.codeInsight.TargetElementUtilBase.findTargetElement(TargetElementUtilBase.java:200)
at com.intellij.codeInsight.TargetElementUtil.findTargetElement(TargetElementUtil.java:60)
at com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass.doCollectInformation(IdentifierHighlighterPass.java:87)
at com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:62)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass$1$1.run(PassExecutorService.java:380)
at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1154)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass$1.run(PassExecutorService.java:371)
at com.intellij.openapi.progress.ProgressManager.executeProcessUnderProgress(ProgressManager.java:209)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:212)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.a(PassExecutorService.java:368)
at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:344)
at com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask.exec(JobLauncherImpl.java:193)
at jsr166e.ForkJoinTask.doExec(ForkJoinTask.java:260)
at jsr166e.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:858)
at jsr166e.ForkJoinPool.scan(ForkJoinPool.java:1687)
at jsr166e.ForkJoinPool.runWorker(ForkJoinPool.java:1642)
at jsr166e.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:109)
请先登录再写评论。
The exception is pretty clear about what's wrong.
http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)
http://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+Architectural+Overview#IntelliJIDEAArchitecturalOverview-Threading
Hi, thanks for that.. I had actually read that page, but somehow missed the threading rules.
My problem now is that I have to get a return value from that thread that will be invoked by
ApplicationManager.getApplication().invokeLater();
Also, a relevant question:
If I use invokeAndWait() instead, the editor will not be blocked right ?
Why do you need to use ApplicationManager.getApplication().invokeLater()?
Are your plugin sources available somewhere?
Yes, I'm trying to fix this issue:
https://github.com/millennialmedia/intellibot/issues/70#issuecomment-56791748
The patch is not working for non-UI threads.
The root problem of why it needs the ApplicationManager.getApplication().invokeLater()
Which is:
FileEditorManager.getInstance(project).getSelectedTextEditor().getDocument()
Is there another way to get that path ?
I'll have to checkout the full sources to understand the context properly.
But it seems to me you're trying to "simulate" resolving of a reference in text by just passing in "String" and current project and trying to find the (relative) context via the active editor? Is this correct? If yes, this should be done completely different.
Yes that is correct.
I am more than open to suggestions :)
You'll want to use PsiReference here. They'll allow to compute resolve targets, completion etc. in a context (element-) dependent way. See https://confluence.jetbrains.com/display/IDEADEV/Developing+Custom+Language+Plugins+for+IntelliJ+IDEA#DevelopingCustomLanguagePluginsforIntelliJIDEA-ReferencesandResolve there's plenty of real world examples in IntelliJ Community source code.