| Summary: | Hyperlink detection for Java source documents from source JARs is broken | ||
|---|---|---|---|
| Product: | z_Archived | Reporter: | Alex Boyko <aboyko> |
| Component: | LSP4E | Assignee: | 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
New Gerrit change created: https://git.eclipse.org/r/137571 Gerrit change https://git.eclipse.org/r/137571 was merged to [master]. Commit: http://git.eclipse.org/c/lsp4e/lsp4e.git/commit/?id=f224bb0f188dedfae175f86015e91b865d94db75 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? 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"
}
}
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 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. 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) (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. I can confirm ... installing the latest snapshot fixed that. Thanks! :D From here: http://download.eclipse.org/lsp4e/snapshots/ @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... (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 ? @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? (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). |