perf: improve Java LSP tool result handoff#1031
Merged
Merged
Conversation
Return structured file and line fields from findSymbol so the model can consume precise ranges without repeating symbol search. Accept line-suffixed Java locations in file structure resolution and document outlineInput handoff. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves the Java LSP Copilot tools’ result “handoff” so downstream steps (e.g., read_file / lsp_java_getFileStructure) can consume lsp_java_findSymbol output more directly, and so file resolution is more tolerant of Java-style path:line inputs and multi-root workspaces.
Changes:
- Enhanced
lsp_java_findSymbolpayload withfile,startLine,endLine, andoutlineInput, and added anextStephint to reduce unnecessary repeat tool calls. - Made file URI resolution tolerate Java location suffixes (e.g.,
src/Foo.java:42) and improved multi-root relative-path handling when the workspace folder name is included. - Updated skill docs, instrument instructions, and tool metadata to prefer
outlineInput/filehandoff patterns.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/copilot/tools/javaContextTools.ts | Adds Java path:line tolerance, improves multi-root relative resolution, and enriches findSymbol results with additional fields and guidance. |
| resources/skills/java-lsp-tools/SKILL.md | Documents the updated findSymbol output fields and the preferred handoff flow using outlineInput/file. |
| resources/instruments/javaLspContext.instructions.md | Updates Java chat instructions to prefer read_file with file/range and getFileStructure with outlineInput. |
| package.json | Updates tool metadata/schema descriptions to reflect new fields and tolerated path:line inputs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Use normalized relative paths consistently when resolving file structure inputs and classify truncated findSymbol responses before small exact-result guidance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the PR focused on the evidence-backed findSymbol handoff contract. Do not claim getFileStructure accepts path:line inputs without telemetry proving that case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep findSymbol results as structured location data and leave next-tool choice to the model. The payload still exposes file, line, range, and outlineInput for downstream consumption without embedding result-level routing guidance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the redundant outlineInput field and keep findSymbol output focused on factual location data: file, startLine, endLine, and range. getFileStructure can consume the returned file when broader file outline context is needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/copilot/tools/javaContextTools.ts:344
- The PR description says
lsp_java_findSymbolwill add anoutlineInputfield and a top-levelnextStephint, but the tool output here only includesfile/startLine/endLine/readFileInputand returns{ results, total }. If those fields are required for handoff, they should be included in the actual payload.
const results = symbols.slice(0, limit).map(s => {
const file = vscode.workspace.asRelativePath(s.location.uri);
const { startLine, endLine } = toInclusiveLineRange(s.location.range);
return {
name: s.name,
kind: vscode.SymbolKind[s.kind],
container: s.containerName || undefined,
file,
startLine,
endLine,
readFileInput: toReadFileInput(file, startLine, endLine),
location: `${file}:${startLine}`,
range: `L${startLine}-${endLine}`,
};
});
resultCount = results.length;
const findSymbolPayload = { results, total: symbols.length };
responseCharCount = getResponseCharCount(findSymbolPayload);
return toResult(findSymbolPayload);
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
modelDescription is sent to the model on every request, so condense both tool descriptions and the uri param description while keeping the read_file (offset/limit) handoff and no-re-search guidance intact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ol name - Use nullish coalescing + Math.floor for getFileStructure limit so an explicit 0 and fractional values are handled correctly. - Use the full lsp_java_findSymbol tool name in the Java LSP instructions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
chagong
approved these changes
Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This draft updates the Java LSP Copilot tool contract so successful symbol and file-outline results are easier to consume by downstream tools, especially VS Code Copilot's built-in
read_file.Recent telemetry analysis showed that raw
findSymbol -> findSymbolis not a reliable problem metric by itself because most adjacent pairs are likely same-round/batch tool calls. The PR therefore avoids prescriptive next-step hints and focuses on factual, read-file-compatible result fields.Changes
lsp_java_findSymbolnow returns structured location fields plus a directread_fileadapter:filestartLineendLinerangereadFileInput: { filePath, offset, limit }location: path:linefield fromfindSymbol;fileis the canonical handoff field forlsp_java_getFileStructure.lsp_java_getFileStructurenow returns a top-levelfileand per-symbol read ranges:startLineendLinerangereadFileRange: { offset, limit }limittolsp_java_getFileStructureto control payload size:2060truncated: truewhen cappedasRelativePathincludes the workspace folder name.Expected experiment signal
This PR is not expected to eliminate all
findSymbol -> findSymboltransitions. Same-round/batch symbol lookups can still be valid.Expected improvements:
findSymbol -> readFilewhen source is needed.findSymbol -> readFile/getFileStructurewithin the next few tool calls.findSymbol -> findSymbolrepeat rate, especially pairs withdelta > 1sordelta > 5s.findSymbolresults.getFileStructurepayloads while preservinggetFileStructure -> readFileconsumption.Metrics that should not be treated as primary success criteria:
findSymbol -> findSymbol, because it is inflated by batch/parallel tool calls.findSymbolto always be followed byread_file;lsp_java_getFileStructure, additional symbol lookup, or generic search can still be valid depending on the task.Intentional non-goals
nextStepfield in tool results; next-tool selection remains with the model.outlineInput;fileis the single path handoff field.path:lineparsing inlsp_java_getFileStructure;findSymbolno longer returns apath:linefield that would encourage this misuse.Validation
npm run compilenpm run tslintnpm testcurrently fails in existing Library Controller tests becausetoReferencedLibraryPath/toReferencedLibraryExcludePathare not exported fromextension_bundle_1; unrelated to this LSP tool change.