Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: LSP cancellation support #1093

Merged
merged 1 commit into from
Aug 10, 2023

Conversation

angelozerr
Copy link
Contributor

perf: LSP cancellation support

Fixes #791

@angelozerr angelozerr force-pushed the cancel_support branch 5 times, most recently from bf8402a to 57ce183 Compare August 10, 2023 07:34
@angelozerr angelozerr marked this pull request as ready for review August 10, 2023 07:38
@angelozerr
Copy link
Contributor Author

The PR is ready and all operations completion, inlayhint, etc managed cancellation support. The cancel support is interesting when language server takes some times to give a response and a new request is called.

You should see now in the trace Sending notification '$/cancelRequest'

[Trace - 09:35:35 AM] Received notification 'textDocument/publishDiagnostics'
[Trace - 09:35:35 AM] Sending notification '$/cancelRequest'
[Trace - 09:35:35 AM] Received response 'textDocument/inlayHint - (2)' in 392ms.
[Trace - 09:35:36 AM] Sending request 'textDocument/inlayHint - (3)'.
[Trace - 09:35:36 AM] Sending notification '$/cancelRequest'
[Trace - 09:35:36 AM] Received response 'textDocument/inlayHint - (3)' in 856ms.
[Trace - 09:35:36 AM] Sending notification 'textDocument/didSave'
[Trace - 09:35:36 AM] Sending notification 'textDocument/didChange'
[Trace - 09:35:37 AM] Sending notification 'textDocument/didSave'
[Trace - 09:35:37 AM] Sending notification 'textDocument/didChange'
[Trace - 09:35:37 AM] Sending request 'textDocument/inlayHint - (4)'.
[Trace - 09:35:37 AM] Sending notification '$/cancelRequest'

As our language server are fast, it can be difficult to produce a cancel.

To reproduce this cancel, I created an application.properties with 1500 lines and I type fast to open / close the completion and you should see $/cancelRequest. I notice too that inlay hint can be slow and sometimes it is canceled with $/cancelRequest.

@angelozerr
Copy link
Contributor Author

Please note that when a cancelRequest occurs it will not cancel the future which is created on IJ side (IndexAwareLanguageClient). We need to do some improvement on our language server

@angelozerr angelozerr force-pushed the cancel_support branch 2 times, most recently from 92082ba to 80183a2 Compare August 10, 2023 10:49
/**
* Itemwhich stores the initialized LSP4j language server and the language server wrapper.
*/
public class LanguageServerItem {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll have to turn this into a record, once Java 17 is required

}
}).filter(Objects::nonNull).collect(Collectors.toList()));
.map(languageServer ->
cancellationSupport.execute(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it runs in async, there's a small risk that at this point cancellationSupport could be null-ed by other methods

@fbricon
Copy link
Contributor

fbricon commented Aug 10, 2023

I opened https://github.com/ia3andy/quarkus-blast/blob/main/src/main/resources/templates/GameController/partials/grid.html, clicked on an inlay hint and got that exception:

java.lang.ClassCastException: class com.redhat.devtools.intellij.lsp4ij.LanguageServerWrapper cannot be cast to class org.eclipse.lsp4j.services.LanguageServer (com.redhat.devtools.intellij.lsp4ij.LanguageServerWrapper and org.eclipse.lsp4j.services.LanguageServer are in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @72128910)
	at com.redhat.devtools.intellij.lsp4ij.operations.inlayhint.LSPInlayHintInlayProvider.lambda$createInlayPresentation$1(LSPInlayHintInlayProvider.java:182)
	at com.intellij.codeInsight.hints.presentation.PresentationFactory$referenceOnHover$hovered$1.invoke(PresentationFactory.kt:278)
	at com.intellij.codeInsight.hints.presentation.PresentationFactory$referenceOnHover$hovered$1.invoke(PresentationFactory.kt:42)
	at com.intellij.codeInsight.hints.presentation.PresentationFactory$onClick$2.invoke(PresentationFactory.kt:251)
	at com.intellij.codeInsight.hints.presentation.PresentationFactory$onClick$2.invoke(PresentationFactory.kt:42)
	at com.intellij.codeInsight.hints.presentation.OnClickPresentation$1.onClick(OnClickPresentation.kt:17)
	at com.intellij.codeInsight.hints.presentation.OnClickPresentation.mouseClicked(OnClickPresentation.kt:21)
	at com.intellij.codeInsight.hints.presentation.DynamicDelegatePresentation.mouseClicked(DynamicDelegatePresentation.kt:53)
	at com.intellij.codeInsight.hints.presentation.StaticDelegatePresentation.mouseClicked(StaticDelegatePresentation.kt:51)
	at com.intellij.codeInsight.hints.presentation.StaticDelegatePresentation.mouseClicked(StaticDelegatePresentation.kt:51)
	at com.intellij.codeInsight.hints.presentation.SequencePresentation$mouseClicked$1.invoke(SequencePresentation.kt:71)
	at com.intellij.codeInsight.hints.presentation.SequencePresentation$mouseClicked$1.invoke(SequencePresentation.kt:16)
	at com.intellij.codeInsight.hints.presentation.SequencePresentation.handleMouse(SequencePresentation.kt:62)
	at com.intellij.codeInsight.hints.presentation.SequencePresentation.mouseClicked(SequencePresentation.kt:70)
	at com.intellij.codeInsight.hints.presentation.InsetPresentation$mouseClicked$1.invoke(InsetPresentation.kt:53)
	at com.intellij.codeInsight.hints.presentation.InsetPresentation$mouseClicked$1.invoke(InsetPresentation.kt:13)
	at com.intellij.codeInsight.hints.presentation.InsetPresentation.handleMouse(InsetPresentation.kt:48)
	at com.intellij.codeInsight.hints.presentation.InsetPresentation.mouseClicked(InsetPresentation.kt:52)
	at com.intellij.codeInsight.hints.presentation.StaticDelegatePresentation.mouseClicked(StaticDelegatePresentation.kt:51)
	at com.intellij.codeInsight.hints.presentation.StaticDelegatePresentation.mouseClicked(StaticDelegatePresentation.kt:51)
	at com.intellij.codeInsight.hints.presentation.DynamicInsetPresentation$mouseClicked$1.invoke(DynamicInsetPresentation.kt:57)
	at com.intellij.codeInsight.hints.presentation.DynamicInsetPresentation$mouseClicked$1.invoke(DynamicInsetPresentation.kt:11)
	at com.intellij.codeInsight.hints.presentation.DynamicInsetPresentation.handleMouse(DynamicInsetPresentation.kt:52)
	at com.intellij.codeInsight.hints.presentation.DynamicInsetPresentation.mouseClicked(DynamicInsetPresentation.kt:56)
	at com.intellij.codeInsight.hints.presentation.RecursivelyUpdatingRootPresentation.mouseClicked(RecursivelyUpdatingRootPresentation.kt:69)
	at com.intellij.codeInsight.hints.LinearOrderInlayRenderer.mouseClicked(LinearOrderInlayRenderer.kt:113)
	at com.intellij.codeInsight.hints.presentation.listeners.InlayEditorMouseListener$mouseClicked$1.run(InlayEditorMouseListener.kt:26)
	at com.intellij.util.SlowOperations.allowSlowOperations(SlowOperations.java:149)
	at com.intellij.codeInsight.hints.presentation.listeners.InlayEditorMouseListener.mouseClicked(InlayEditorMouseListener.kt:25)
	at com.intellij.openapi.editor.impl.event.EditorEventMulticasterImpl$2.lambda$mouseClicked$1(EditorEventMulticasterImpl.java:73)
	at com.intellij.openapi.extensions.impl.ExtensionProcessingHelper.forEachExtensionSafe(ExtensionProcessingHelper.java:34)
	at com.intellij.openapi.extensions.ExtensionPointName.forEachExtensionSafe(ExtensionPointName.java:46)
	at com.intellij.openapi.editor.impl.event.EditorEventMulticasterImpl$2.mouseClicked(EditorEventMulticasterImpl.java:73)
	at com.intellij.openapi.editor.impl.EditorImpl$MyMouseAdapter.runMouseClickedCommand(EditorImpl.java:3954)
	at com.intellij.openapi.editor.impl.EditorImpl$MyMouseAdapter.mouseReleased(EditorImpl.java:3873)
	at java.desktop/java.awt.Component.processMouseEvent(Component.java:6648)
	at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3392)
	at java.desktop/java.awt.Component.processEvent(Component.java:6413)
	at java.desktop/java.awt.Container.processEvent(Container.java:2266)
	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5022)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2802)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:781)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:730)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:724)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:754)
	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:752)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:751)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:898)
	at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.java:820)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:743)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$6(IdeEventQueue.java:439)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:791)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$7(IdeEventQueue.java:438)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:113)
	at com.intellij.ide.IdeEventQueue.performActivity(IdeEventQueue.java:604)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:436)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:881)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:484)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)

@fbricon
Copy link
Contributor

fbricon commented Aug 10, 2023

Also saw this in my logs:

SEVERE: Internal error: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.CompletionStage.toCompletableFuture()" because the return value of "java.util.function.Function.apply(Object)" is null
java.util.concurrent.CompletionException: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.CompletionStage.toCompletableFuture()" because the return value of "java.util.function.Function.apply(Object)" is null
	at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
	at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320)
	at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1159)
	at java.base/java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:483)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.CompletionStage.toCompletableFuture()" because the return value of "java.util.function.Function.apply(Object)" is null
	at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
	... 6 more

No idea what caused it.

@sonarcloud
Copy link

sonarcloud bot commented Aug 10, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
No Duplication information No Duplication information

@angelozerr
Copy link
Contributor Author

Also saw this in my logs:

I don't know -(

@angelozerr
Copy link
Contributor Author

I opened https://github.com/ia3andy/quarkus-blast/blob/main/src/main/resources/templates/GameController/partials/grid.html, clicked on an inlay hint and got that exception:

Should be fixed

@fbricon fbricon merged commit afe404b into redhat-developer:main Aug 10, 2023
11 checks passed
@fbricon
Copy link
Contributor

fbricon commented Aug 10, 2023

Thanks @angelozerr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LSP cancellation support
2 participants