eclipse-lsp4e / eclipse-lsp4e/lsp4e

LSPDocumentAbstractHandler.setEnabled can cause an UI freeze

Open
#1,331 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
85
Forks
69
Avg merge
8h 33m
Merged PRs (30d)
6

Description

We have observed the following UI freeze caused by LSP4E:

!ENTRY org.eclipse.ui.monitoring 2 0 2025-07-21 10:01:26.475
!MESSAGE UI freeze of 0.36s at 10:01:26.097
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2025-07-21 10:01:26.475
!MESSAGE Sample at 10:01:26.298 (+0.201s)
Thread 'main' tid=1 (TIMED_WAITING)
!STACK 0
Stack Trace
	at java.base@17.0.5/jdk.internal.misc.Unsafe.park(Native Method)
	at java.base@17.0.5/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:252)
	at java.base@17.0.5/java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1866)
	at java.base@17.0.5/java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3463)
	at java.base@17.0.5/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3434)
	at java.base@17.0.5/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1939)
	at java.base@17.0.5/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2095)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor.matches(LSPDocumentAbstractHandler.java:69)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor.lambda$0(LSPDocumentAbstractHandler.java:59)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor$$Lambda$1693/0x0000000801a61638.test(Unknown Source)
	at java.base@17.0.5/java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90)
	at java.base@17.0.5/java.util.AbstractList$RandomAccessSpliterator.tryAdvance(AbstractList.java:706)
	at java.base@17.0.5/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base@17.0.5/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base@17.0.5/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base@17.0.5/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base@17.0.5/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
	at java.base@17.0.5/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
	at java.base@17.0.5/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base@17.0.5/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:632)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor.anyMatching(LSPDocumentAbstractHandler.java:59)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler.setEnabled(LSPDocumentAbstractHandler.java:123)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler.setEnabled(LSPDocumentAbstractHandler.java:113)
	at org.eclipse.lsp4e.operations.rename.LSPRenameHandler.setEnabled(LSPRenameHandler.java:74)
	at org.eclipse.ui.internal.handlers.HandlerProxy.setEnabled(HandlerProxy.java:223)
	at org.eclipse.ui.internal.handlers.E4HandlerProxy.setEnabled(E4HandlerProxy.java:134)
	at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
	at java.base@17.0.5/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base@17.0.5/java.lang.reflect.Method.invoke(Method.java:568)
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:299)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:233)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:174)
	at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.setEnabled(HandlerServiceHandler.java:91)
	at org.eclipse.core.commands.Command.setEnabled(Command.java:856)
	at org.eclipse.ui.menus.CommandContributionItem.isEnabled(CommandContributionItem.java:932)
	at org.eclipse.ui.menus.CommandContributionItem.updateMenuItem(CommandContributionItem.java:536)
	at org.eclipse.ui.menus.CommandContributionItem.update(CommandContributionItem.java:486)
	at org.eclipse.jface.action.MenuManager.update(MenuManager.java:857)
	at org.eclipse.jface.action.MenuManager.update(MenuManager.java:857)
	at org.eclipse.ui.internal.Workbench.updateActiveWorkbenchWindowMenuManager(Workbench.java:3246)
	at org.eclipse.ui.internal.Workbench.lambda$0(Workbench.java:3228)
	at org.eclipse.ui.internal.Workbench$$Lambda$397/0x0000000801196540.bindingManagerChanged(Unknown Source)
	at org.eclipse.jface.bindings.BindingManager.fireBindingManagerChanged(BindingManager.java:896)
	at org.eclipse.jface.bindings.BindingManager.setActiveBindings(BindingManager.java:2178)
	at org.eclipse.jface.bindings.BindingManager.recomputeBindings(BindingManager.java:1737)
	at org.eclipse.jface.bindings.BindingManager.contextManagerChanged(BindingManager.java:693)
	at org.eclipse.core.commands.contexts.ContextManager.fireContextManagerChanged(ContextManager.java:164)
	at org.eclipse.core.commands.contexts.ContextManager.setEventCaching(ContextManager.java:323)
	at org.eclipse.core.commands.contexts.ContextManager.deferUpdates(ContextManager.java:85)
	at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.activate(PartServiceImpl.java:787)

Even though the handler waits for a max of 50ms, there are plenty of subclasses of LSPDocumentAbstractHandler, so calling setEnable on several of these these when opening/activating an editor (or starting the workbench) can cumulate to a noticeable UI freeze.

Since the code is prepared to return false and enable the handler asynchronously when the completableFuture finishes, I think we can eliminate the UI freeze by lowering the timeout to lower number, for example 5ms.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in LSPDocumentAbstractHandler.java, especially setEnabled and LanguageServerDocumentHandlerExecutor.matches/anyMatching around the CompletableFuture wait shown in the stack trace. Inspect the handler subclasses and existing tests, then verify that the enabled-state check no longer causes cumulative UI blocking while asynchronous completion still updates the handler correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
devtools, performance
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.