Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,15 @@
{
"name": "lsp_java_getFileStructure",
"toolReferenceName": "javaFileStructure",
"modelDescription": "Get the outline (classes, methods, fields) of a Java file with symbol kinds and line ranges.\n\nUse before read_file to find specific line ranges. For searching across files, use lsp_java_findSymbol instead.\n\nOnly use file paths confirmed from prior tool results or user input. If unsure, call lsp_java_findSymbol first.",
"modelDescription": "Get the outline of a known Java file: classes, interfaces, methods, fields, symbol kinds, and line ranges.\n\nUse this after lsp_java_findSymbol returns a relevant file, or when the user already provided a Java file path. It helps choose a precise read_file range instead of reading the whole file.\n\nDo not use this for workspace-wide search. For Java class, method, or field lookup across files, use lsp_java_findSymbol first. Only pass file paths confirmed by the user or prior tool results; do not guess paths. Do not call this repeatedly for the same file unless the first result was empty or stale.",
"displayName": "Java: Get File Structure",
"userDescription": "Get a Java file outline with classes, methods, fields, and line ranges.",
"tags": [
"java",
"lsp",
"code-navigation",
"file-outline"
],
"canBeReferencedInPrompt": true,
"icon": "$(symbol-class)",
"when": "config.vscode-java-dependency.enableLspTools && javaLSReady",
Expand All @@ -73,8 +80,15 @@
{
"name": "lsp_java_findSymbol",
"toolReferenceName": "javaFindSymbol",
"modelDescription": "Search for Java symbol definitions (classes, interfaces, methods, fields) across the entire workspace by name. Returns precise locations in ~60 tokens vs ~500+ tokens from grep_search.\n\nWhen to use:\n- To find where a class, method, or field is defined — faster and more precise than grep_search\n- To discover file paths before using other tools\n- Supports partial matching (e.g. 'UserSvc' finds 'UserServiceImpl')\n\nWhen NOT to use:\n- For non-Java files\n- To search for string literals, comments, or non-symbol text (use grep_search)",
"modelDescription": "Search Java symbols across the workspace by identifier and return concise definition locations.\n\nUse for precise Java class, interface, method, or field navigation. Prefer this over grep_search, file_search, semantic_search, or search subagents when the user is looking for a Java symbol by name or partial identifier.\n\nAfter this returns relevant symbols, do not call lsp_java_findSymbol again with the same or similar query. Continue with lsp_java_getFileStructure for the returned file, or read_file only the relevant line range.\n\nDo not use for non-Java files, string literals, comments, build files, XML, natural-language concepts, or broad codebase exploration. If there are no matches, retry at most once with a shorter materially different identifier, then fall back to generic search.",
"displayName": "Java: Find Symbol",
"userDescription": "Find Java class, method, field, or interface definitions by name.",
"tags": [
"java",
"lsp",
"code-navigation",
"symbol-search"
],
"canBeReferencedInPrompt": true,
"icon": "$(search)",
"when": "config.vscode-java-dependency.enableLspTools && javaLSReady",
Expand Down
9 changes: 5 additions & 4 deletions resources/instruments/javaLspContext.instructions.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
---
description: REQUIRED for Java files. Provides compiler-accurate lsp_java_findSymbol and lsp_java_getFileStructure tools that replace grep_search, search_subagent, semantic_search, and file_search for Java symbol navigation.
description: Use Java LSP tools for precise Java symbol navigation. Prefer lsp_java_findSymbol and lsp_java_getFileStructure over generic search only when locating Java classes, methods, fields, or file outlines.
applyTo: '**/*.java'
---

For Java files, two compiler-accurate `lsp_java_*` tools are available and return structured results in ~50 tokens vs ~500+ from generic search:
For Java symbol navigation, two compiler-accurate `lsp_java_*` tools are available and return structured results with smaller, easier-to-interpret payloads than generic search:

- `lsp_java_findSymbol(query)` — find class/method/field definitions by name across the workspace
- `lsp_java_getFileStructure(uri)` — get file outline (classes, methods, fields) with line ranges

These are deferred tools. Load them with `tool_search_tool_regex` using pattern `lsp_java_` before first use.
If these tools are not already available in the current tool list, load them with `tool_search` using a query such as `Java LSP symbol navigation lsp_java`.

Prefer these over `grep_search`, `search_subagent`, `semantic_search`, `file_search`, or full-file `read_file` when navigating Java symbols. Always use `findSymbol` to discover file paths before passing them to `getFileStructure` — do not guess paths. Fall back to `grep_search` if a tool returns empty or errors.
Use `lsp_java_findSymbol` before `grep_search`, `search_subagent`, `semantic_search`, or `file_search` only when the task is to locate Java symbols by name or partial identifier. If it returns relevant symbols, do not call it again with the same or similar query; next use `lsp_java_getFileStructure` for the returned file or `read_file` on the smallest useful line range.

Use `lsp_java_getFileStructure` only with a path confirmed by the user or a previous tool result. Do not guess paths. Use generic search for string literals, comments, XML, Gradle/Maven files, non-Java files, or broad conceptual exploration. If `findSymbol` returns no matches, retry at most once with a shorter, materially different identifier before falling back to generic search.
16 changes: 10 additions & 6 deletions resources/skills/java-lsp-tools/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,45 @@
---
name: java-lsp-tools
description: Compiler-accurate Java code navigation via the Java Language Server. Use lsp_java_findSymbol to locate symbols and lsp_java_getFileStructure to inspect file outlines. Prefer over grep_search for Java symbol navigation.
description: Compiler-accurate Java symbol navigation via the Java Language Server. Use lsp_java_findSymbol for Java identifiers and lsp_java_getFileStructure for known Java files; prefer them over generic search only for symbol/file-outline navigation.
---

# Java LSP Tools

Two compiler-accurate tools backed by the Java Language Server (jdtls). They return structured JSON with fewer tokens than `grep_search` or `read_file`.
Two compiler-accurate tools backed by the Java Language Server (jdtls). They return structured JSON that is easier to interpret than generic search results for Java symbol navigation.

## Tools

### `lsp_java_findSymbol`
Search for Java symbol definitions (classes, methods, fields) by name across the workspace. Supports partial matching.
- Input: `{ query, limit? }` — limit defaults to 20, max 50
- Output: `{ name, kind, location }` per result (~60 tokens)
- **Use instead of** `grep_search` when looking for where a class/method is defined
- **Use instead of** `grep_search`, `file_search`, `semantic_search`, or `search_subagent` when looking for where a Java class/method/field is defined by identifier
- Do not repeat with the same or similar query after relevant results are returned

### `lsp_java_getFileStructure`
Get hierarchical outline of a Java file (classes, methods, fields) with line ranges.
- Input: `{ uri }` — workspace-relative path. Must be a known path from prior tool results or user input — do not guess
- Output: symbol tree with `L start-end` ranges (~100 tokens)
- **Use instead of** `read_file` full scan when you need to understand a file's layout
- **Use before** `read_file` when you need to choose a precise line range in a known Java file

## When to Use

| Task | Use | Not |
|---|---|---|
| Find class/method/field definition | `lsp_java_findSymbol` | `grep_search` |
| See file outline before reading | `lsp_java_getFileStructure` | `read_file` full file |
| See known Java file outline before reading | `lsp_java_getFileStructure` | `read_file` full file |
| Search non-Java files (xml, gradle) | `grep_search` | lsp tools |
| Search string literals or comments | `grep_search` | lsp tools |
| Explore broad concepts without identifiers | `semantic_search` or `search_subagent` | lsp tools |

## Typical Workflow

**findSymbol → getFileStructure → read_file (specific lines only)**

If `findSymbol` returns relevant symbols, move forward to `getFileStructure` or `read_file`; do not call `findSymbol` again with the same or similar identifier.

## Fallback

- `findSymbol` returns empty → retry with shorter keyword, then fall back to `grep_search`
- `findSymbol` returns empty → retry at most once with a shorter, materially different identifier, then fall back to `grep_search`
- Path error → use `findSymbol` to discover correct path first
- Tool error / jdtls not ready → fall back to `grep_search` + `read_file`, don't retry more than once
2 changes: 2 additions & 0 deletions src/copilot/tools/javaContextTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,9 @@ const findSymbolTool: vscode.LanguageModelTool<FindSymbolInput> = {
const results = symbols.slice(0, limit).map(s => ({
name: s.name,
kind: vscode.SymbolKind[s.kind],
container: s.containerName || undefined,
location: `${vscode.workspace.asRelativePath(s.location.uri)}:${s.location.range.start.line + 1}`,
range: `L${s.location.range.start.line + 1}-${s.location.range.end.line + 1}`,
}));
resultCount = results.length;
const findSymbolPayload = { results, total: symbols.length };
Expand Down
Loading