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)


I can't find how to fix this...

It is possible that I am following a totally wrong aproach ?

Thanks!
9 comments
Comment actions Permalink

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 ?

0
Comment actions Permalink

Why do you need to use ApplicationManager.getApplication().invokeLater()?
Are your plugin sources available somewhere?

0
Comment actions Permalink

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.

0
Comment actions Permalink

The root problem of why it needs the ApplicationManager.getApplication().invokeLater()

is the way it's getting the path of the selected file that's active on the editor.
Which is:

FileEditorManager.getInstance(project).getSelectedTextEditor().getDocument()

Is there another way to get that path ?
0
Comment actions Permalink

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.

0
Comment actions Permalink

Yes that is correct.

I am more than open to suggestions :)

0
Comment actions Permalink

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.

0

Please sign in to leave a comment.