Skip to content
Merged
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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
{
"name": "lsp_java_getFileStructure",
"toolReferenceName": "javaFileStructure",
"modelDescription": "Get the structure (classes, methods, fields, inner classes) of a Java file. Returns a hierarchical outline with symbol kinds and line ranges in ~100 tokens.\n\nWhen to use:\n- Before reading a Java file, to understand its layout and find specific line ranges\n- Instead of read_file on the entire file — use this first, then read_file on specific lines\n- When you need to know what methods/fields a class has\n\nWhen NOT to use:\n- For non-Java files (use read_file instead)\n- To search across multiple files (use lsp_java_findSymbol instead)",
"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.",
"displayName": "Java: Get File Structure",
"canBeReferencedInPrompt": true,
"icon": "$(symbol-class)",
Expand All @@ -62,7 +62,7 @@
"properties": {
"uri": {
"type": "string",
"description": "Java file path (workspace-relative or full URI)"
"description": "Workspace-relative path to a Java file. Must be a known path from prior tool results or user input — do not guess."
}
},
"required": [
Expand Down
2 changes: 1 addition & 1 deletion resources/instruments/javaLspContext.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ For Java files, two compiler-accurate `lsp_java_*` tools are available and retur

These are deferred tools. Load them with `tool_search_tool_regex` using pattern `lsp_java_` before first use.

Prefer these over `grep_search`, `search_subagent`, `semantic_search`, `file_search`, or full-file `read_file` when navigating Java symbols. Fall back to `grep_search` if a tool returns empty or errors.
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.

2 changes: 1 addition & 1 deletion resources/skills/java-lsp-tools/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Search for Java symbol definitions (classes, methods, fields) by name across the

### `lsp_java_getFileStructure`
Get hierarchical outline of a Java file (classes, methods, fields) with line ranges.
- Input: `{ uri }` — workspace-relative path or full URI
- 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

Expand Down
16 changes: 12 additions & 4 deletions src/copilot/tools/javaContextTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* - No classpath resolution, no dependency download
*/

import * as path from "path";
import * as vscode from "vscode";
import { Commands } from "../../commands";
import { sendInfo } from "vscode-extension-telemetry-wrapper";
Expand Down Expand Up @@ -56,14 +57,14 @@ function resolveFileUri(input: string): vscode.Uri {

let uri: vscode.Uri;

// Full URI — only allow the file: scheme
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(input) || /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(input)) {
if (input.includes("://")) {
// URI string (e.g. "file:///home/user/project/src/Main.java")
uri = vscode.Uri.parse(input);
if (uri.scheme !== "file") {
throw new Error(`Unsupported URI scheme "${uri.scheme}". Only file: URIs are allowed.`);
}
} else if (input.startsWith("/") || /^[a-zA-Z]:[/\\]/.test(input)) {
// Absolute path (Unix or Windows)
} else if (path.isAbsolute(input)) {
// Absolute filesystem path (Unix or Windows)
uri = vscode.Uri.file(input);
} else {
// Relative path — resolve against first workspace folder
Expand Down Expand Up @@ -99,6 +100,13 @@ const fileStructureTool: vscode.LanguageModelTool<FileStructureInput> = {
let errorMessage = "";
try {
const uri = resolveFileUri(options.input.uri);
try {
await vscode.workspace.fs.stat(uri);
} catch {
status = "error";
errorMessage = `File not found: ${vscode.workspace.asRelativePath(uri)}`;
return toResult({ error: errorMessage });
}
const symbols = await vscode.commands.executeCommand<vscode.DocumentSymbol[]>(
"vscode.executeDocumentSymbolProvider", uri,
);
Expand Down
Loading