Skip to content

feat(lsp): use official LSP SDK and implement didSave for real-time diagnostics#91

Open
BingqingLyu wants to merge 1 commit into
mainfrom
fork-pr-3170-lsp-didSave
Open

feat(lsp): use official LSP SDK and implement didSave for real-time diagnostics#91
BingqingLyu wants to merge 1 commit into
mainfrom
fork-pr-3170-lsp-didSave

Conversation

@BingqingLyu

@BingqingLyu BingqingLyu commented Apr 27, 2026

Copy link
Copy Markdown
Owner

TLDR

Integrate official vscode-languageserver-protocol SDK for LSP types and implement textDocument/didSave notification to enable real-time diagnostics updates after file edits.

Screenshots / Video Demo

N/A — this is an internal infrastructure change. The effect is that LSP diagnostics now update immediately after edits are applied.

Dive Deeper

Problem

Previously, after applying code edits via the Edit tool, LSP diagnostics would not update until the user manually triggered a refresh. This made it difficult to verify fixes immediately.

Solution

  1. Official LSP SDK: Added vscode-languageserver-protocol dependency and use official types (InitializeParams, InitializeResult, ServerCapabilities) instead of custom definitions. This ensures type compatibility with the LSP specification.

  2. didSave Notification: Implemented notifyDocumentSaved that sends textDocument/didSave to LSP servers after edits. This triggers servers (like gopls, typescript-language-server) to re-read the file from disk and update their diagnostics.

  3. Capability Handling:

    • Client now declares synchronization.didSave: true capability
    • Server capabilities are stored from initialize result
    • getSaveCapability properly handles TextDocumentSyncOptions and TextDocumentSyncKind variants

Files Changed

  • types.ts: Use lsp.InitializeParams/InitializeResult/ServerCapabilities
  • LspServerManager.ts: Store capabilities from initialize result, declare didSave capability
  • NativeLspService.ts: Implement notifyDocumentSaved and getSaveCapability
  • NativeLspClient.ts: Add notifyDocumentSaved method
  • coreToolScheduler.ts: Call notifyDocumentSaved after Edit tool execution

Test Coverage

Added comprehensive tests for notifyDocumentSaved:

  • Server with save capability (object with includeText)
  • Server without save support (TextDocumentSyncKind.None)
  • textDocumentSync as number (Full or Incremental)
  • save capability as boolean
  • Targeting specific server via serverName parameter
  • Graceful error handling when connection fails
  • Integration with CoreToolScheduler (edit tool triggers notification)

Known Limitations

Reviewer Test Plan

  1. Start qwen-code in a Go project with gopls configured
  2. Use the LSP tool to get diagnostics on a file
  3. Introduce a syntax error via Edit tool
  4. Run diagnostics again - should immediately show the new error
  5. Fix the error via Edit tool
  6. Run diagnostics again - should show no errors

Verified with gopls

Tested in a single session with edit + diagnostics invoked together:

  • Introduced error: unknown field undefinedField in struct literal
  • Diagnostics immediately detected: [ERROR] 28:28 (MissingLitField) [compiler]: unknown field undefinedField
  • Fixed the error, diagnostics returned: No diagnostics found

This confirms that didSave notification triggers gopls to re-analyze the file and update diagnostics in real-time.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Linked issues / bugs

Related to QwenLM#3029 - This PR provides an alternative approach to PR QwenLM#3034 for triggering LSP diagnostics refresh after edits. While PR QwenLM#3034 uses didClose + didOpen with publishDiagnostics caching, this PR uses didSave which is lighter and more semantically correct for post-edit updates. Both approaches are complementary: PR QwenLM#3034's caching is essential for push-only servers (like typescript-language-server), while this PR's didSave provides a cleaner refresh mechanism for edit operations.


🤖 Generated with Qwen Code

…iagnostics

- Add vscode-languageserver-protocol dependency for official LSP types
- Use lsp.InitializeParams/InitializeResult/ServerCapabilities from SDK
- Implement notifyDocumentSaved to trigger LSP diagnostics refresh after edits
- Add client capability synchronization.didSave to register for save notifications
- Store server capabilities from initialize result for capability checks
@BingqingLyu

BingqingLyu commented May 7, 2026

Copy link
Copy Markdown
Owner Author

Conflict Group 1

This PR shares modified functions with 2 other PR(s): #85, #96.

These PRs should be reviewed as a batch — merging one may affect the others.

Function File Also modified by
doStartServer LspServerManager.ts #85
executeSingleToolCall coreToolScheduler.ts #96
initializeLspServer LspServerManager.ts #85
graph LR
    PR91["PR #91"]
    FdoStartServer_2706["doStartServer<br>LspServerManager.ts"]
    PR91 -->|modifies| FdoStartServer_2706
    PR85["PR #85"]
    PR85 -->|modifies| FdoStartServer_2706
    FexecuteSingleToolCall_1638["executeSingleToolCall<br>coreToolScheduler.ts"]
    PR91 -->|modifies| FexecuteSingleToolCall_1638
    PR96["PR #96"]
    PR96 -->|modifies| FexecuteSingleToolCall_1638
    FinitializeLspServer_2706["initializeLspServer<br>LspServerManager.ts"]
    PR91 -->|modifies| FinitializeLspServer_2706
    PR85 -->|modifies| FinitializeLspServer_2706
Loading

Posted by codegraph-ai conflict detection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflicting-group-1 Conflicting PR group 1 — review as a batch conflicting-pr Shares at least one cross-PR dependency with other PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants