github / github/copilot-cli

Java LSP : Hover definition works but definition doesn't

Offen
#2,105 0 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen
area:tools
Vorherrschende Sprache
Shell
Sterne
11.2k
Forks
1.9k
Ø Merge
14 Std. 16 Min.
Gemergte PRs (30 T.)
6

Beschreibung

### Describe the bug

`goToDefinition` via the LSP tool returns "No definition found" for **all types defined in Maven/Gradle dependency JARs** (e.g., Spring Framework, LangChain4j), even though `hover` at the exact same position correctly returns full type info and Javadoc from those same JARs.

### Root cause

During JDTLS initialization, the Copilot CLI does not send `extendedClientCapabilities.classFileContentsSupport: true` in `initializationOptions`. Without this flag, JDTLS will not return `jdt://` URIs in `textDocument/definition` responses for classes inside JARs — it returns null instead.

The relevant code in `app.js` constructs `initializationOptions` from `this.config.lspInitializationOptions`, but `lsp-config.json` has no such field, so it is `undefined`.

### Steps to reproduce

1. Configure JDTLS in `~/.copilot/lsp-config.json`:
```json
{
"lspServers": {
"java": {
"command": "jdtls",
"args": ["-data", "/tmp/jdtls-workspace"],
"fileExtensions": { ".java": "java" }
}
}
}
```
2. Open any Java project with Maven/Gradle dependencies
3. Run `hover` on a dependency type (e.g., `ChatModel` from LangChain4j, or `@Controller` from Spring):
```
> lsp hover ChatModel on line 43
✅ Returns: "dev.langchain4j.model.chat.ChatModel — Represents a language model..."
Source: langchain4j-core-1.11.0.jar
```
4. Run `goToDefinition` at the **exact same position**:
```
> lsp goToDefinition ChatModel on line 43
❌ Returns: "No definition found at line 43, character 25."
```

This affects all dependency types — Spring (`@Controller`, `@GetMapping`), LangChain4j (`ChatModel`, `UserMessage`), etc. Navigation to project-local classes works fine.

### Proposed fix

**1. Send `extendedClientCapabilities` during JDTLS initialization:**

Add `classFileContentsSupport: true` to the initialization options sent to JDTLS. This could be done via a new `lspInitializationOptions` field in `lsp-config.json`, or hardcoded for the Java/JDTLS server:

```json
{
"initializationOptions": {
"extendedClientCapabilities": {
"classFileContentsSupport": true
}
}
}
```

With this flag, JDTLS will return `LocationLink` objects with `jdt://contents/...` URIs for classes in JARs.

**2. Handle `jdt://` URIs in definition responses:**

When the LSP tool receives a definition result with a `jdt://` URI:
- Send a `java/classFileContents` request to JDTLS with that URI
- JDTLS responds with the decompiled (or source-attached) Java source code
- Display the source at the indicated range, similar to how VS Code shows read-only decompiled class files

### Additional context

The `getClientCapabilities()` method in `app.js` already declares `definition: { linkSupport: true }`, so the LSP protocol side is correct. The only missing piece is the JDTLS-specific `extendedClientCapabilities`.

This would also benefit `goToImplementation` for interfaces defined in JARs, and `findReferences` completeness for dependency types.

Related: #1349 (broader Java/JVM ecosystem awareness)

### Additional context

### Environment

- **Copilot CLI**: 1.0.6
- **JDTLS**: 1.57.0 (via Homebrew)
- **OS**: macOS (Apple Silicon)
- **Java project**: Spring Boot with Maven dependencies

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.