Repository navigation
Semantic Highlighting breaks when rapidly typing due to improper cancellation #2216
Description
Activity
- addedIssue-BugA bug to squash.A bug to squash.Needs: TriageMaintainer attention needed!Maintainer attention needed!
on Nov 3, 2024 - removedNeeds: TriageMaintainer attention needed!Maintainer attention needed!
on Nov 4, 2024 JustinGrote commented
on Nov 4, 2024 CollaboratorMore actionsThanks for the submission Martin! Keep them coming, I plan to look more into it once I finish up the logging PR, it will help to give much better visibility into what's going on.
Reacted by MartinGC94 and Andy JordanJustinGrote commented
on Jan 30, 2025 CollaboratorMore actionsI looked into this some more and it looks like things are working fine up to a point where the delta semanticTokens doesn't get a response, and I assume vscode is hanging the semantic provider waiting on this response for that particular document.
No idea why it isn't responding, but the SemanticTokensHandler has a custom omnisharp base class SemanticTokensHandlerBase that handles all the delta stuff automatically and asks us for a
Tokenizemethod to provide it the tokens, which is a bit of an odd method: it gives us a builder, asks us to push tokens to the builder, then return a completed task.I'll look into this more to see if I can find why it is hanging on not sending the response.
JustinGrote commented
on Jan 30, 2025 CollaboratorMore actionsSo it seems to be that if the operation is canceled, somewhere that's not getting handled correctly. If you do one edit at a time and wait, it works fine, it's when you type at such a rate that the operation gets cancelled in favor of a new one that seems to bunch it up.
I think it has something to do with the textDocument/completion getting cancelled causing the semanticTokens response to get cancelled somehow, and therefore vscode doesn't ever respond, so we need to make sure the semanticTokens response always replies or at least also replies with a cancelled
JustinGrote commented
on Jan 30, 2025 CollaboratorMore actionsOK, I'm very sure it's this problem: OmniSharp/csharp-language-server-protocol#784
Implementing the workaround fixes it, however the average request processing goes up to 500ms with a lot of typing, which is unacceptable. Going to need to either fix this upstream or potentially create our own custom SemanticToken handler and not rely on the base one here.
Reacted by MartinGC94Nice find!
I don't know much about LSP but the name indicates that C# is using this as well. Since semantic tokens work fine there, maybe it's worth checking out how they solved it without this performance issue?JustinGrote commented
on Jan 30, 2025 CollaboratorMore actionsMartinGC94 unfortunately the "Omnisharp" LSP in the C# extension has been replaced by a closed source LSP, they no longer use this as their underlying engine, and there's real concern it's going to be abandoned as it is the foundation of our entire extension, certainly development and issue fixing has all but stopped based on the commit history.
So, assuming I can find a way to gracefully cancel this (hopefully the cancellation process mentioned in the issue triggers the cancellation token and doesn't just hard kill the tasks) within the extension, it should be fixable. If it has to be fixed in the LSP, we will have to beg them to release a new version otherwise we may have to fork/innersource it for future.
JustinGrote commented
on Jan 30, 2025 CollaboratorMore actionsI checked the Bicep implementation which uses the same omnisharp LSP, and I didn't see any kind of special handling there, so maybe it also affects them, I'll have to test to be sure.
https://github.com/Azure/bicep/tree/main/src/Bicep.LangServer- changed the title
[-]Semantic highlighting doesn't apply to text that is typed[/-][+]Semantic Highlighting breaks when rapidly typing due to improper cancellation[/+]on Jan 30, 2025 JustinGrote commented
on Jan 30, 2025 CollaboratorMore actionsJustinGrote commented
on Jan 30, 2025 CollaboratorMore actionsIt appears the cancellation of the completionHandler causes an unhandled cancellation exception in our
GetCommandInfoAsynchere, most likely because we have passed our handler cancellation token toExecutePSCommandAsyncand it is throwing it after doing whatever graceful shutdown it needs to do:
IReadOnlyList results = await executionService.DidChangedandCompletionare the only two LSP commands that I see in the log that are considered "serial" commands and trigger the parallel to serial engine change. I'm not sure why Completion would be that way, maybe we try overriding it to parallel? We can always cancel it if we get aDidChangedand the client can request a restart.Whatever is happening there apparently isn't "cleaning up" in the way Omnisharp wants in order to proceed, so the semantic response never gets sent, and it stops working beyond that point as the client is still waiting for the first semantic response (there doesn't seem to be any sort of configurable timeout)
It seems to mostly trigger on when you hit a completion when typing with an active completion already in flight to the LSP (as completions can take 300-800ms sometimes).
CC Andy Jordan (@andyleejordan) for help. I'm not quite sure what the coordination is expected to be in the event of a cancellationToken here.
Exception has occurred: CLR/System.Threading.Tasks.TaskCanceledException An exception of type 'System.Threading.Tasks.TaskCanceledException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'A task was canceled.' at Microsoft.PowerShell.EditorServices.Services.PowerShell.Utility.CommandHelpers.<GetCommandInfoAsync>d__8.MoveNext() in D:\PowerShellEditorServices\src\PowerShellEditorServices\Services\PowerShell\Utility\CommandHelpers.cs:line 147 at Microsoft.PowerShell.EditorServices.Handlers.PsesCompletionHandler.<Handle>d__14.MoveNext() in D:\PowerShellEditorServices\src\PowerShellEditorServices\Services\TextDocument\Handlers\CompletionHandler.cs:line 165 at OmniSharp.Extensions.LanguageServer.Server.Pipelines.SemanticTokensDeltaPipeline`2.<Handle>d__0.MoveNext() at OmniSharp.Extensions.LanguageServer.Server.Pipelines.ResolveCommandPipeline`2.<Handle>d__3.MoveNext() at MediatR.Pipeline.RequestPreProcessorBehavior`2.<Handle>d__2.MoveNext() at MediatR.Pipeline.RequestPostProcessorBehavior`2.<Handle>d__2.MoveNext() at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.<Handle>d__2.MoveNext()JustinGrote commented
on Jan 31, 2025 CollaboratorMore actionsCan't believe I didn't spot this earlier. In registration our completion handler has been forced to serial mode, and I'm guessing Omnisharp didn't account/test for this.
Patrick Meinecke (@SeeminglyScience) since not all handlers go thru the pipeline like the semantic handler, maybe there's a better way to approach this?
JustinGrote commented
on Jan 31, 2025 CollaboratorMore actionsRemoving the serial does fix it, the cancellation still happens but it doesn't cause the parallel to serial switch (since all commands past didChange are parallel) and doesn't cause the semantic to be cancelled.
- linked a pull request that will close this issueFix semantic highlighting cancellation during rapid typing #2301
on Jun 10, 2026




Prerequisites
Summary
Like the title says, semantic highlighting doesn't work for any new text you type, it only works for the text that was already there when you opened a file. Interestingly the VS code token inspect feature correctly lists the semantic color but the visuals aren't updated. Initially I assumed this was a bug in VS code itself but if I try it with the C# extension it works perfectly fine in VS code so they must be doing something different from this extension.
Here's a clip that demonstrates the issue:
Highlight.Bug.mp4
PowerShell Version
Visual Studio Code Version
Extension Version
ms-vscode.powershell@2024.5.0Steps to Reproduce
Enable semantic highlighting with colors that don't match the colors from the textmate highlighting and start typing.
Visuals
No response
Logs
No response