mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 19:52:02 +00:00
Key changes: 1. Remove LspLanguageDetector — LSP is now fully config-driven via .lsp.json or extensions. No more auto-detected built-in presets that fail when the server binary is missing. 2. Add ensureDocumentOpen — send textDocument/didOpen before every document-level LSP request (definitions, references, hover, documentSymbol, implementations, prepareCallHierarchy, diagnostics, codeActions). This fixes the root cause of most methods returning empty results (Issue #2106, #1873). 3. Add retry mechanism for slow servers — when a freshly opened document yields empty results on non-TypeScript servers (jdtls, clangd, pylsp), wait 2s and retry once. This mirrors the existing retry logic in workspaceSymbols. 4. Handle LSP 3.17 WorkspaceSymbol format — location.range is now optional in normalizeSymbolResult, fixing jdtls workspace symbol responses that omit the range field. 5. Improve workspace symbol warmup — for non-TypeScript servers, open a workspace file before the first workspace/symbol request and retry on empty results after a warmup delay. 6. Track warmup-opened URIs — warmupTypescriptServer now returns the opened URI, which is registered with ensureDocumentOpen to prevent duplicate didOpen notifications. Closes #2106, closes #1873 Made-with: Cursor
417 lines
12 KiB
Markdown
417 lines
12 KiB
Markdown
# Language Server Protocol (LSP) Support
|
|
|
|
Qwen Code provides native Language Server Protocol (LSP) support, enabling advanced code intelligence features like go-to-definition, find references, diagnostics, and code actions. This integration allows the AI agent to understand your code more deeply and provide more accurate assistance.
|
|
|
|
## Overview
|
|
|
|
LSP support in Qwen Code works by connecting to language servers that understand your code. Once you configure servers via `.lsp.json` (or extensions), Qwen Code can start them and use them to:
|
|
|
|
- Navigate to symbol definitions
|
|
- Find all references to a symbol
|
|
- Get hover information (documentation, type info)
|
|
- View diagnostic messages (errors, warnings)
|
|
- Access code actions (quick fixes, refactorings)
|
|
- Analyze call hierarchies
|
|
|
|
## Quick Start
|
|
|
|
LSP is an experimental feature in Qwen Code. To enable it, use the `--experimental-lsp` command line flag:
|
|
|
|
```bash
|
|
qwen --experimental-lsp
|
|
```
|
|
|
|
LSP servers are configuration-driven. You must define them in `.lsp.json` (or via extensions) for Qwen Code to start them.
|
|
|
|
### Prerequisites
|
|
|
|
You need to have the language server for your programming language installed:
|
|
|
|
| Language | Language Server | Install Command |
|
|
| --------------------- | -------------------------- | ------------------------------------------------------------------------------ |
|
|
| TypeScript/JavaScript | typescript-language-server | `npm install -g typescript-language-server typescript` |
|
|
| Python | pylsp | `pip install python-lsp-server` |
|
|
| Go | gopls | `go install golang.org/x/tools/gopls@latest` |
|
|
| Rust | rust-analyzer | [Installation guide](https://rust-analyzer.github.io/manual.html#installation) |
|
|
| C/C++ | clangd | Install LLVM/clangd via your package manager |
|
|
| Java | jdtls | Install JDTLS and a JDK |
|
|
|
|
## Configuration
|
|
|
|
### .lsp.json File
|
|
|
|
You can configure language servers using a `.lsp.json` file in your project root. This uses the language-keyed format described in the [Claude Code plugin LSP configuration reference](https://code.claude.com/docs/en/plugins-reference#lsp-servers).
|
|
|
|
**Basic format:**
|
|
|
|
```json
|
|
{
|
|
"typescript": {
|
|
"command": "typescript-language-server",
|
|
"args": ["--stdio"],
|
|
"extensionToLanguage": {
|
|
".ts": "typescript",
|
|
".tsx": "typescriptreact",
|
|
".js": "javascript",
|
|
".jsx": "javascriptreact"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### C/C++ (clangd) configuration
|
|
|
|
Dependencies:
|
|
|
|
- clangd (LLVM) must be installed and available in PATH.
|
|
- A compile database (`compile_commands.json`) or `compile_flags.txt` is required for accurate results.
|
|
|
|
Example:
|
|
|
|
```json
|
|
{
|
|
"cpp": {
|
|
"command": "clangd",
|
|
"args": [
|
|
"--background-index",
|
|
"--clang-tidy",
|
|
"--header-insertion=iwyu",
|
|
"--completion-style=detailed"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Java (jdtls) configuration
|
|
|
|
Dependencies:
|
|
|
|
- JDK installed and available in PATH (`java`).
|
|
- JDTLS installed and available in PATH (`jdtls`).
|
|
|
|
Example:
|
|
|
|
```json
|
|
{
|
|
"java": {
|
|
"command": "jdtls",
|
|
"args": ["-configuration", ".jdtls-config", "-data", ".jdtls-workspace"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Configuration Options
|
|
|
|
#### Required Fields
|
|
|
|
| Option | Type | Description |
|
|
| --------- | ------ | ------------------------------------------------- |
|
|
| `command` | string | Command to start the LSP server (must be in PATH) |
|
|
|
|
#### Optional Fields
|
|
|
|
| Option | Type | Default | Description |
|
|
| ----------------------- | -------- | --------- | ------------------------------------------------------- |
|
|
| `args` | string[] | `[]` | Command line arguments |
|
|
| `transport` | string | `"stdio"` | Transport type: `stdio`, `tcp`, or `socket` |
|
|
| `env` | object | - | Environment variables |
|
|
| `initializationOptions` | object | - | LSP initialization options |
|
|
| `settings` | object | - | Server settings via `workspace/didChangeConfiguration` |
|
|
| `extensionToLanguage` | object | - | Maps file extensions to language identifiers |
|
|
| `workspaceFolder` | string | - | Override workspace folder (must be within project root) |
|
|
| `startupTimeout` | number | `10000` | Startup timeout in milliseconds |
|
|
| `shutdownTimeout` | number | `5000` | Shutdown timeout in milliseconds |
|
|
| `restartOnCrash` | boolean | `false` | Auto-restart on crash |
|
|
| `maxRestarts` | number | `3` | Maximum restart attempts |
|
|
| `trustRequired` | boolean | `true` | Require trusted workspace |
|
|
|
|
### TCP/Socket Transport
|
|
|
|
For servers that use TCP or Unix socket transport:
|
|
|
|
```json
|
|
{
|
|
"remote-lsp": {
|
|
"transport": "tcp",
|
|
"socket": {
|
|
"host": "127.0.0.1",
|
|
"port": 9999
|
|
},
|
|
"extensionToLanguage": {
|
|
".custom": "custom"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Available LSP Operations
|
|
|
|
Qwen Code exposes LSP functionality through the unified `lsp` tool. Here are the available operations:
|
|
|
|
### Code Navigation
|
|
|
|
#### Go to Definition
|
|
|
|
Find where a symbol is defined.
|
|
|
|
```
|
|
Operation: goToDefinition
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
- line: Line number (1-based)
|
|
- character: Column number (1-based)
|
|
```
|
|
|
|
#### Find References
|
|
|
|
Find all references to a symbol.
|
|
|
|
```
|
|
Operation: findReferences
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
- line: Line number (1-based)
|
|
- character: Column number (1-based)
|
|
- includeDeclaration: Include the declaration itself (optional)
|
|
```
|
|
|
|
#### Go to Implementation
|
|
|
|
Find implementations of an interface or abstract method.
|
|
|
|
```
|
|
Operation: goToImplementation
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
- line: Line number (1-based)
|
|
- character: Column number (1-based)
|
|
```
|
|
|
|
### Symbol Information
|
|
|
|
#### Hover
|
|
|
|
Get documentation and type information for a symbol.
|
|
|
|
```
|
|
Operation: hover
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
- line: Line number (1-based)
|
|
- character: Column number (1-based)
|
|
```
|
|
|
|
#### Document Symbols
|
|
|
|
Get all symbols in a document.
|
|
|
|
```
|
|
Operation: documentSymbol
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
```
|
|
|
|
#### Workspace Symbol Search
|
|
|
|
Search for symbols across the workspace.
|
|
|
|
```
|
|
Operation: workspaceSymbol
|
|
Parameters:
|
|
- query: Search query string
|
|
- limit: Maximum results (optional)
|
|
```
|
|
|
|
### Call Hierarchy
|
|
|
|
#### Prepare Call Hierarchy
|
|
|
|
Get the call hierarchy item at a position.
|
|
|
|
```
|
|
Operation: prepareCallHierarchy
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
- line: Line number (1-based)
|
|
- character: Column number (1-based)
|
|
```
|
|
|
|
#### Incoming Calls
|
|
|
|
Find all functions that call the given function.
|
|
|
|
```
|
|
Operation: incomingCalls
|
|
Parameters:
|
|
- callHierarchyItem: Item from prepareCallHierarchy
|
|
```
|
|
|
|
#### Outgoing Calls
|
|
|
|
Find all functions called by the given function.
|
|
|
|
```
|
|
Operation: outgoingCalls
|
|
Parameters:
|
|
- callHierarchyItem: Item from prepareCallHierarchy
|
|
```
|
|
|
|
### Diagnostics
|
|
|
|
#### File Diagnostics
|
|
|
|
Get diagnostic messages (errors, warnings) for a file.
|
|
|
|
```
|
|
Operation: diagnostics
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
```
|
|
|
|
#### Workspace Diagnostics
|
|
|
|
Get all diagnostic messages across the workspace.
|
|
|
|
```
|
|
Operation: workspaceDiagnostics
|
|
Parameters:
|
|
- limit: Maximum results (optional)
|
|
```
|
|
|
|
### Code Actions
|
|
|
|
#### Get Code Actions
|
|
|
|
Get available code actions (quick fixes, refactorings) at a location.
|
|
|
|
```
|
|
Operation: codeActions
|
|
Parameters:
|
|
- filePath: Path to the file
|
|
- line: Start line number (1-based)
|
|
- character: Start column number (1-based)
|
|
- endLine: End line number (optional, defaults to line)
|
|
- endCharacter: End column (optional, defaults to character)
|
|
- diagnostics: Diagnostics to get actions for (optional)
|
|
- codeActionKinds: Filter by action kind (optional)
|
|
```
|
|
|
|
Code action kinds:
|
|
|
|
- `quickfix` - Quick fixes for errors/warnings
|
|
- `refactor` - Refactoring operations
|
|
- `refactor.extract` - Extract to function/variable
|
|
- `refactor.inline` - Inline function/variable
|
|
- `source` - Source code actions
|
|
- `source.organizeImports` - Organize imports
|
|
- `source.fixAll` - Fix all auto-fixable issues
|
|
|
|
## Security
|
|
|
|
LSP servers are only started in trusted workspaces by default. This is because language servers run with your user permissions and can execute code.
|
|
|
|
### Trust Controls
|
|
|
|
- **Trusted Workspace**: LSP servers start if configured
|
|
- **Untrusted Workspace**: LSP servers won't start unless `trustRequired: false` is set in the server configuration
|
|
|
|
To mark a workspace as trusted, use the `/trust` command or configure trusted folders in settings.
|
|
|
|
### Per-Server Trust Override
|
|
|
|
You can override trust requirements for specific servers in their configuration:
|
|
|
|
```json
|
|
{
|
|
"safe-server": {
|
|
"command": "safe-language-server",
|
|
"args": ["--stdio"],
|
|
"trustRequired": false,
|
|
"extensionToLanguage": {
|
|
".safe": "safe"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Server Not Starting
|
|
|
|
1. **Check if the server is installed**: Run the command manually to verify
|
|
2. **Check the PATH**: Ensure the server binary is in your system PATH
|
|
3. **Check workspace trust**: The workspace must be trusted for LSP
|
|
4. **Check logs**: Look for error messages in the console output
|
|
5. **Verify --experimental-lsp flag**: Make sure you're using the flag when starting Qwen Code
|
|
|
|
### Slow Performance
|
|
|
|
1. **Large projects**: Consider excluding `node_modules` and other large directories
|
|
2. **Server timeout**: Increase `startupTimeout` in server configuration for slow servers
|
|
|
|
### No Results
|
|
|
|
1. **Server not ready**: The server may still be indexing
|
|
2. **File not saved**: Save your file for the server to pick up changes
|
|
3. **Wrong language**: Check if the correct server is running for your language
|
|
|
|
### Debugging
|
|
|
|
Enable debug logging to see LSP communication:
|
|
|
|
```bash
|
|
DEBUG=lsp* qwen --experimental-lsp
|
|
```
|
|
|
|
Or check the LSP debugging guide at `packages/cli/LSP_DEBUGGING_GUIDE.md`.
|
|
|
|
## Claude Code Compatibility
|
|
|
|
Qwen Code supports Claude Code-style `.lsp.json` configuration files in the language-keyed format defined in the [Claude Code plugins reference](https://code.claude.com/docs/en/plugins-reference#lsp-servers). If you're migrating from Claude Code, use the language-as-key layout in your configuration.
|
|
|
|
### Configuration Format
|
|
|
|
The recommended format follows Claude Code's specification:
|
|
|
|
```json
|
|
{
|
|
"go": {
|
|
"command": "gopls",
|
|
"args": ["serve"],
|
|
"extensionToLanguage": {
|
|
".go": "go"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Claude Code LSP plugins can also supply `lspServers` in `plugin.json` (or a referenced `.lsp.json`). Qwen Code loads those configs when the extension is enabled, and they must use the same language-keyed format.
|
|
|
|
## Best Practices
|
|
|
|
1. **Install language servers globally**: This ensures they're available in all projects
|
|
2. **Use project-specific settings**: Configure server options per project when needed via `.lsp.json`
|
|
3. **Keep servers updated**: Update your language servers regularly for best results
|
|
4. **Trust wisely**: Only trust workspaces from trusted sources
|
|
|
|
## FAQ
|
|
|
|
### Q: How do I enable LSP?
|
|
|
|
Use the `--experimental-lsp` flag when starting Qwen Code:
|
|
|
|
```bash
|
|
qwen --experimental-lsp
|
|
```
|
|
|
|
### Q: How do I know which language servers are running?
|
|
|
|
Use the `/lsp status` command to see all configured and running language servers.
|
|
|
|
### Q: Can I use multiple language servers for the same file type?
|
|
|
|
Yes, but only one will be used for each operation. The first server that returns results wins.
|
|
|
|
### Q: Does LSP work in sandbox mode?
|
|
|
|
LSP servers run outside the sandbox to access your code. They're subject to workspace trust controls.
|