Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 544794

Summary: Hyperlink detection for Java source documents from source JARs is broken
Product: z_Archived Reporter: Alex Boyko <aboyko>
Component: LSP4EAssignee: Alex Boyko <aboyko>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: andreas.hoehmann, mistria, mlippert, vlad.andronache
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: All   
See Also: https://git.eclipse.org/r/137571
https://git.eclipse.org/c/lsp4e/lsp4e.git/commit/?id=f224bb0f188dedfae175f86015e91b865d94db75
Whiteboard:

Description Alex Boyko CLA 2019-02-25 15:16:05 EST
LSP4E hyper link detection throws NPE for Java docs with content from a source JAR.
For example if java.io.File source is in the editor. No hyper links shown...
Exception in the log:
java.lang.NullPointerException
	at org.eclipse.lsp4e.operations.declaration.OpenDeclarationHyperlinkDetector.detectHyperlinks(OpenDeclarationHyperlinkDetector.java:79)
	at org.eclipse.ui.texteditor.HyperlinkDetectorRegistry$HyperlinkDetectorDelegate.detectHyperlinks(HyperlinkDetectorRegistry.java:81)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.findHyperlinks(HyperlinkManager.java:289)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.findHyperlinks(HyperlinkManager.java:262)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.mouseMove(HyperlinkManager.java:457)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:216)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4319)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1512)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1535)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1520)
	at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1324)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4143)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3760)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1173)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1062)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:156)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:636)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:563)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:151)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:155)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:400)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:595)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1501)
Comment 1 Eclipse Genie CLA 2019-02-25 16:21:23 EST
New Gerrit change created: https://git.eclipse.org/r/137571
Comment 3 Mickael Istria CLA 2019-02-26 02:43:25 EST
Before we mark it as resolve, here is a topic for discussion: should we send some notifications with jar:file:/..../File.java in this case? Would this provide anything valuable?
Comment 4 Alex Boyko CLA 2019-02-28 11:35:06 EST
You mean document opened, document closed messages?

VSCode sends those i think as I've seen this:
[Trace - 11:31:34 AM] Sending notification 'textDocument/didClose'.
Params: {
    "textDocument": {
        "uri": "jdt://contents/spring-web-5.0.8.RELEASE.jar/org.springframework.web.bind.annotation/RestController.class?%3Dinject-demo%2F%5C%2FUsers%5C%2Faboyko%5C%2F.m2%5C%2Frepository%5C%2Forg%5C%2Fspringframework%5C%2Fspring-web%5C%2F5.0.8.RELEASE%5C%2Fspring-web-5.0.8.RELEASE.jar%3Corg.springframework.web.bind.annotation%28RestController.class"
    }
}
Comment 5 Mickael Istria CLA 2019-02-28 12:28:33 EST
Right, i've opened https://github.com/eclipse/eclipse.jdt.ls/issues/943 to jdt.ls for this oddity.
I was just wondering whether there woukf be some value to you if we try to have LSP4E send open/close notifications for class with the standard jar:file:/path/to/jar!path/in/jar.class URI pattern
Comment 6 Alex Boyko CLA 2019-02-28 17:44:29 EST
It won't bring value right away I think because we don't handle such doc URI yet as we don't handle JDT LS jdt URIs either.
However, it would bring value down the road as we'd be interested in highlighting beans and provide boot hovers for the the resources living in source JARs.
So, yes, I'd add those messages...

Meanwhile we could try and the above for the JDT LS case...

I looked briefly at JDT LS issue discussion... project is important for us as well, because we attempt to parse java doc to build the AST and run a visitor on it. Types need to be resolved hence we need the project to get the classpath and pass that on to the ASTParser environment.
Comment 7 Andreas Höhmann CLA 2019-03-07 02:54:00 EST
I have a similar error ... but for me it happens only in a mylyn task-editor:

java.lang.NullPointerException
	at org.eclipse.lsp4e.operations.declaration.OpenDeclarationHyperlinkDetector.detectHyperlinks(OpenDeclarationHyperlinkDetector.java:79)
	at org.eclipse.ui.texteditor.HyperlinkDetectorRegistry$HyperlinkDetectorDelegate.detectHyperlinks(HyperlinkDetectorRegistry.java:81)
	at org.eclipse.mylyn.internal.tasks.ui.editors.AbstractHyperlinkTextPresentationManager.getRegions(AbstractHyperlinkTextPresentationManager.java:138)
	at org.eclipse.mylyn.internal.tasks.ui.editors.AbstractHyperlinkTextPresentationManager.computeStyleRanges(AbstractHyperlinkTextPresentationManager.java:93)
	at org.eclipse.mylyn.internal.tasks.ui.editors.AbstractHyperlinkTextPresentationManager$Support.applyTextPresentation(AbstractHyperlinkTextPresentationManager.java:64)
	at org.eclipse.jface.text.TextViewer.changeTextPresentation(TextViewer.java:4721)
	at org.eclipse.jface.text.presentation.PresentationReconciler.applyTextRegionCollection(PresentationReconciler.java:562)
	at org.eclipse.jface.text.presentation.PresentationReconciler.processDamage(PresentationReconciler.java:551)
	at org.eclipse.jface.text.presentation.PresentationReconciler.access$3(PresentationReconciler.java:547)
	at org.eclipse.jface.text.presentation.PresentationReconciler$InternalListener.inputDocumentChanged(PresentationReconciler.java:121)
	at org.eclipse.jface.text.TextViewer.fireInputDocumentChanged(TextViewer.java:2744)
	at org.eclipse.jface.text.TextViewer.setDocument(TextViewer.java:2785)
	at org.eclipse.jface.text.source.SourceViewer.setDocument(SourceViewer.java:663)
	at org.eclipse.jface.text.source.SourceViewer.setDocument(SourceViewer.java:613)
	at org.eclipse.mylyn.internal.tasks.ui.editors.RichTextEditor.updateDocument(RichTextEditor.java:250)
	at org.eclipse.mylyn.internal.tasks.ui.editors.RichTextEditor.configure(RichTextEditor.java:195)
	at org.eclipse.mylyn.internal.tasks.ui.editors.RichTextEditor.createControl(RichTextEditor.java:311)
	at org.eclipse.mylyn.internal.tasks.ui.editors.RichTextAttributeEditor.createControl(RichTextAttributeEditor.java:87)
	at org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorSummaryPart.addSummaryText(TaskEditorSummaryPart.java:126)
	at org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorSummaryPart.createControl(TaskEditorSummaryPart.java:177)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.initializePart(AbstractTaskEditorPage.java:1277)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.access$7(AbstractTaskEditorPage.java:1269)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage$14.run(AbstractTaskEditorPage.java:818)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createParts(AbstractTaskEditorPage.java:809)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createParts(AbstractTaskEditorPage.java:788)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createFormContentInternal(AbstractTaskEditorPage.java:683)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createFormContent(AbstractTaskEditorPage.java:628)
	at org.eclipse.ui.forms.editor.FormPage.lambda$0(FormPage.java:166)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:72)
	at org.eclipse.ui.forms.editor.FormPage.createPartControl(FormPage.java:166)
	at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createPartControl(AbstractTaskEditorPage.java:588)
	at org.eclipse.ui.forms.editor.FormEditor.pageChange(FormEditor.java:483)
	at org.eclipse.ui.part.MultiPageEditorPart.setActivePage(MultiPageEditorPart.java:1080)
	at org.eclipse.ui.forms.editor.FormEditor.setActivePage(FormEditor.java:617)
	at org.eclipse.ui.forms.editor.SharedHeaderFormEditor.setActivePage(SharedHeaderFormEditor.java:117)
	at org.eclipse.mylyn.tasks.ui.editors.TaskEditor.addPages(TaskEditor.java:419)
	at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:143)
	at org.eclipse.ui.forms.editor.SharedHeaderFormEditor.createPages(SharedHeaderFormEditor.java:104)
	at org.eclipse.mylyn.tasks.ui.editors.TaskEditor.createPages(TaskEditor.java:200)
	at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:351)
	at org.eclipse.ui.internal.e4.compatibility.CompatibilityPart.createPartControl(CompatibilityPart.java:156)
	at org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor.createPartControl(CompatibilityEditor.java:102)
	at org.eclipse.ui.internal.e4.compatibility.CompatibilityPart.create(CompatibilityPart.java:367)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
	at org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(InjectorImpl.java:1001)
	at org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(InjectorImpl.java:966)
	at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:139)
	at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:411)
	at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:333)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:193)
	at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:108)
	at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:77)
	at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:59)
	at org.eclipse.e4.ui.workbench.renderers.swt.ContributedPartRenderer.createWidget(ContributedPartRenderer.java:132)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:1015)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:675)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:781)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:752)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:746)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:730)
	at org.eclipse.e4.ui.internal.workbench.PartServiceImpl$1.handleEvent(PartServiceImpl.java:107)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler.lambda$0(UIEventHandler.java:38)
	at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:236)
	at org.eclipse.ui.internal.UISynchronizer.syncExec(UISynchronizer.java:147)
	at org.eclipse.swt.widgets.Display.syncExec(Display.java:4580)
	at org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(E4Application.java:219)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:38)
	at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:233)
	at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
	at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
	at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
	at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
	at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
	at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
	at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
	at org.eclipse.e4.ui.model.application.ui.impl.ElementContainerImpl.setSelectedElement(ElementContainerImpl.java:177)
	at org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.showElementInWindow(ModelServiceImpl.java:641)
	at org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.bringToTop(ModelServiceImpl.java:605)
	at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.delegateBringToTop(PartServiceImpl.java:791)
	at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.bringToTop(PartServiceImpl.java:404)
	at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.showPart(PartServiceImpl.java:1240)
	at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:3317)
	at org.eclipse.ui.internal.WorkbenchPage.lambda$9(WorkbenchPage.java:3216)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:72)
	at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:3213)
	at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:3177)
	at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:3158)
	at org.eclipse.mylyn.tasks.ui.TasksUiUtil.openEditor(TasksUiUtil.java:182)
	at org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal.openTask(TasksUiInternal.java:997)
	at org.eclipse.mylyn.tasks.ui.TasksUiUtil.openTask(TasksUiUtil.java:278)
	at org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal.refreshAndOpenTaskListElement(TasksUiInternal.java:319)
	at org.eclipse.mylyn.internal.tasks.ui.actions.OpenTaskListElementAction.runWithEvent(OpenTaskListElementAction.java:56)
	at org.eclipse.mylyn.internal.tasks.ui.actions.OpenTaskListElementAction.run(OpenTaskListElementAction.java:47)
	at org.eclipse.mylyn.internal.tasks.ui.views.TaskListView$19.open(TaskListView.java:1065)
	at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:853)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
	at org.eclipse.ui.internal.JFaceUtil.lambda$0(JFaceUtil.java:47)
	at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:176)
	at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:850)
	at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1165)
	at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:276)
	at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:271)
	at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:311)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4131)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1055)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3944)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3547)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1173)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1062)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:156)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:636)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:563)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:151)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:155)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:400)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:595)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1501)
Comment 8 Martin Lippert CLA 2019-03-07 02:56:52 EST
(In reply to Andreas  Hoehmann from comment #7)
> I have a similar error ... but for me it happens only in a mylyn task-editor:

Someone reported this on the STS4 issue tracker, too:
https://github.com/spring-projects/sts4/issues/207

But it is the same underlying problem, so if you install the latest lsp4e snapshot build, the mylyn task editor works nicely again.
Comment 9 Andreas Höhmann CLA 2019-03-12 04:34:13 EDT
I can confirm ... installing the latest snapshot fixed that. Thanks! :D
Comment 10 Andreas Höhmann CLA 2019-03-12 04:34:36 EDT
From here: http://download.eclipse.org/lsp4e/snapshots/
Comment 11 Alex Boyko CLA 2019-04-24 20:59:26 EDT
@Mickael I got to the point when I'd like to get doc opened message for a source in the JAR doc. In other words with the jar URL. What were you initial thought on extracting that jar schema URI?
I thought that i should modify LSEclipseUtils#toUri(IDocument document) method. If file URI cannot be found for a document try all editor reference that have editor created (i.e. getEditor(false) is not null). Find the editor viewer with matching document and get the editor input and try to get to the URI from the editor input... but I don't see a jar URI there unfortunately... unless I get access to JDTs IClassFile probably...
Comment 12 Mickael Istria CLA 2019-04-25 04:15:39 EDT
(In reply to Alex Boyko from comment #11)
> @Mickael I got to the point when I'd like to get doc opened message for a
> source in the JAR doc. In other words with the jar URL. What were you
> initial thought on extracting that jar schema URI?

I don't have concrete implementation to suggest, I was just wondering whether this was protifable and worth trying, without considering the "how" yet.

> I thought that i should modify LSEclipseUtils#toUri(IDocument document)
> method. If file URI cannot be found for a document try all editor reference
> that have editor created (i.e. getEditor(false) is not null). Find the
> editor viewer with matching document and get the editor input and try to get
> to the URI from the editor input... but I don't see a jar URI there
> unfortunately... unless I get access to JDTs IClassFile probably...

We cannot add a dependency to JDT in LSP4E.
If we can have the jar and resource location from wherever, then we could rebuild the URI.  What we should try to find is how an IDocument is created for an InternalClassFileEditorInput. I see this class implements IPathEditorInput, maybe the getPath() is used.
The approach of looking open editor inputs is also interesting.
Maybe we should simply check with JDT whether the InternalClassFileEditorInput could implement IURIEditorInput and gives the jar:file:/.../!path/to/file.class URI as result of getURI ?
Comment 13 Alex Boyko CLA 2019-04-30 17:31:31 EDT
@Mikael
I had implemented IURIEditorInput in InternalClassFileEditorInput and returned the JDT URI the same way JDT LS builds it for Java element. In addition i had to return content type for class file document which i returned from ClassFileDocumentProvider.
I'm seeing that LSP4E attempts to start LS once some LS supported feature is asked for (hover, codelens, etc) not quite when the editor is opened. Is this correct? I see that doc opened is sent when DocSync is created and that is created when LS is started or found upon some LS feature request (i.e hover, codelens). So not when file buffer is created. However, disconnect from the LS, doc closed message, occurs on buffer disposed. Anyway, was a bit surprised that we don't send document open message when buffer is created or editor opened... it's rather being sent when someting needs to be done like CodeLenses needs to be provided etc. Wonder it it'd work as well if editor doesn't support CodeLens and maybe no hover but reconciling needs to be done... i.e. feels like there might a situation when editor opened, recociling needs to be done by LS but there is nothing to trigger doc opened message sent.
Anyway, with the above, I have LS started for .class files which is great and LS features are available to these docs. Unclear a bit when to send document closed message for .class files...

There is no TextFileBufferManager that i could add a listener and track when .class doc can be disconnected from the LS. My only idea is use DocumentProvider because it keeps track of connected/disconnected input numbers. If I could add a listener to doc provider to signal when input is connected for the first time and disconnected completely then i could probably implement the doc closed message sending correctly. This means changes to Eclipse UI: create IDocumentProviderExtension6 that allows to add /remove input connection listener. What do you think? Anything better you can recommend? Do you see some potential holes in what I'm proposing?
Comment 14 Mickael Istria CLA 2019-05-06 04:48:02 EDT
(In reply to Alex Boyko from comment #13)
> I'm seeing that LSP4E attempts to start LS once some LS supported feature is
> asked for (hover, codelens, etc) not quite when the editor is opened. Is
> this correct?

It's not bad, but the startup of LS should happen earlier, when document is created, as implemented in ConnectDocumentToLanguageServerSetupParticipant.
I think you should put a breakpoint in there and check whether it goes as expected (my guess is that it doesn't because of buffer.getLocation() being null or too different from expectation).