Skip to content

Restore original LSP diagnostic message before forwarding to server#2238

Open
NSExceptional wants to merge 1 commit into
swiftlang:mainfrom
NSExceptional:fix-clangd-codeaction-after-message-mutation
Open

Restore original LSP diagnostic message before forwarding to server#2238
NSExceptional wants to merge 1 commit into
swiftlang:mainfrom
NSExceptional:fix-clangd-codeaction-after-message-mutation

Conversation

@NSExceptional
Copy link
Copy Markdown

@NSExceptional NSExceptional commented May 16, 2026

Summary

  • DiagnosticsManager capitalizes and strips (fix available) from incoming LSP diagnostic messages for display. That mutated message is stored in the DiagnosticCollection and is the one VS Code subsequently puts into context.diagnostics on textDocument/codeAction requests.
  • clangd matches diagnostics in context.diagnostics against its fix-it cache by (range, message) (ClangdLSPServer.hstruct DiagKey). A mutated message means the lookup misses and no quickfix comes back.
  • Stash the pre-mutation message on each diagnostic and add a provideCodeActions middleware that restores it before forwarding. Display-side behavior is unchanged.

This is the user-visible symptom in swiftlang/sourcekit-lsp#2186 (no "Add method implementation" quickfix for -Wincomplete-implementation warnings on Objective-C files). With this patch, the existing clangd fix-it round-trips through vscode-swift end-to-end.

Repro before this PR

Project with an @interface declaring methods and an @implementation that doesn't define all of them:

  • Foo.h: declares -bravo: and +charlie
  • Foo.m: @implementation Foo (alpha only)

clangd publishes two -Wincomplete-implementation warnings. Cursor on Foo in @implementation Foo, hit Cmd+. → no code actions appear. With the fix, the menu shows:

  • "Apply fix: insert - (void)bravo:(NSString *)s {…"
  • "Apply fix: insert + (NSInteger)charlie {…"

The clangd FIXME at ClangdLSPServer.h:246-249 notes that long-term clangd should switch to using Diagnostic.data. That's being addressed separately; this PR is the immediate fix on the client side.

Test plan

  • tsc --noEmit clean
  • eslint clean
  • npm run compile clean
  • CI runs the new DiagnosticsManager.test.ts (stashes original, no-op when nothing was mutated)
  • Manual repro in VS Code with an iOS/Obj-C project that has missing method implementations

Yes, I authored this with my $200 Claude plan, I hope that's okay — it is the only way I can find the time to contribute features and bug fixes to the projects I love

DiagnosticsManager mutates incoming LSP diagnostic messages for display
(capitalizing the first letter, stripping the clangd `(fix available)`
suffix). The mutated message is the one stored in the
DiagnosticCollection and the one VS Code later puts into
`context.diagnostics` when sending textDocument/codeAction.

clangd matches diagnostics in `context.diagnostics` against its fix-it
cache by `(range, message)` (see ClangdLSPServer.h `struct DiagKey`).
A mutated message means the lookup misses and no quickfix is returned —
visible to users as missing "Add method implementation" code actions
for `-Wincomplete-implementation` warnings on Objective-C files.

Stash the pre-mutation message on the diagnostic and add a
`provideCodeActions` middleware that restores it before forwarding to
the server. Display-side behavior is unchanged.

Fixes the user-visible symptom in
swiftlang/sourcekit-lsp#2186 for Objective-C
quickfixes routed through clangd.
@NSExceptional NSExceptional force-pushed the fix-clangd-codeaction-after-message-mutation branch from 8ae6500 to 432b765 Compare May 16, 2026 08:09
@matthewbastien
Copy link
Copy Markdown
Member

Thank you for putting this up! My first thought is that this is a fairly complicated solution that involves mutating VS Code's diagnostic objects. Especially considering that the extension probably shouldn't even be modifying the diagnostics coming back from the compiler/LSP in the first place.

Can you raise a corresponding issue with clear steps to reproduce (or ideally a sample project)? I'd like to take a closer look at this. The DiagnostcsManager code is fairly old at this point and probably needs a re-work in general.

@NSExceptional
Copy link
Copy Markdown
Author

@matthewbastien Done! Let me know if you need anything else!

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.

2 participants