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
116 changes: 2 additions & 114 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. Use this first when you need to understand a file's layout before reading specific sections.",
"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)",
"displayName": "Java: Get File Structure",
"canBeReferencedInPrompt": true,
"icon": "$(symbol-class)",
Expand All @@ -71,7 +71,7 @@
{
"name": "lsp_java_findSymbol",
"toolReferenceName": "javaFindSymbol",
"modelDescription": "Search for Java symbols (classes, interfaces, methods, fields) across the workspace by name. Supports partial/fuzzy matching. Use this to find where a class or method is defined.",
"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)",
"displayName": "Java: Find Symbol",
"canBeReferencedInPrompt": true,
"icon": "$(search)",
Expand All @@ -90,118 +90,6 @@
},
"required": ["query"]
}
},
{
"name": "lsp_java_getFileImports",
"toolReferenceName": "javaFileImports",
"modelDescription": "Get all import statements from a Java file, classified by source (jdk/project/external).",
"displayName": "Java: Get File Imports",
"canBeReferencedInPrompt": true,
"icon": "$(references)",
"when": "config.vscode-java-dependency.enableLspTools && javaLSReady",
"inputSchema": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "Java file path (workspace-relative or full URI)"
}
},
"required": ["uri"]
}
},
{
"name": "lsp_java_getTypeAtPosition",
"toolReferenceName": "javaTypeAtPosition",
"modelDescription": "Get the compiler-resolved type signature at a specific position. Returns fully qualified type, method signature, or field declaration. Use this when you see var, lambdas, or generics and need the exact type.",
"displayName": "Java: Get Type at Position",
"canBeReferencedInPrompt": true,
"icon": "$(symbol-field)",
"when": "config.vscode-java-dependency.enableLspTools && javaLSReady",
"inputSchema": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "Java file path (workspace-relative or full URI)"
},
"line": {
"type": "number",
"description": "Zero-based line number"
},
"character": {
"type": "number",
"description": "Zero-based character offset"
}
},
"required": ["uri", "line", "character"]
}
},
{
"name": "lsp_java_getCallHierarchy",
"toolReferenceName": "javaCallHierarchy",
"modelDescription": "Get incoming callers or outgoing callees of a method. PREFER THIS over grep_search when you need to find which methods call a specific method — returns precise call sites without noise from comments, imports, or string matches. Use 'incoming' for callers, 'outgoing' for callees.",
"displayName": "Java: Get Call Hierarchy",
"canBeReferencedInPrompt": true,
"icon": "$(call-incoming)",
"when": "config.vscode-java-dependency.enableLspTools && javaLSReady",
"inputSchema": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "Java file path (workspace-relative or full URI)"
},
"line": {
"type": "number",
"description": "Zero-based line number of the method"
},
"character": {
"type": "number",
"description": "Zero-based character offset within the method name"
},
"direction": {
"type": "string",
"enum": ["incoming", "outgoing"],
"default": "incoming",
"description": "'incoming' for callers, 'outgoing' for callees"
}
},
"required": ["uri", "line", "character", "direction"]
}
},
{
"name": "lsp_java_getTypeHierarchy",
"toolReferenceName": "javaTypeHierarchy",
"modelDescription": "Get supertypes or subtypes/implementors of a type. PREFER THIS over grep_search('extends|implements') — returns only actual inheritance relationships. Use 'supertypes' for parents, 'subtypes' for children.",
"displayName": "Java: Get Type Hierarchy",
"canBeReferencedInPrompt": true,
"icon": "$(type-hierarchy)",
"when": "config.vscode-java-dependency.enableLspTools && javaLSReady",
"inputSchema": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "Java file path (workspace-relative or full URI)"
},
"line": {
"type": "number",
"description": "Zero-based line number of the type"
},
"character": {
"type": "number",
"description": "Zero-based character offset within the type name"
},
"direction": {
"type": "string",
"enum": ["supertypes", "subtypes"],
"default": "supertypes",
"description": "'supertypes' for parents, 'subtypes' for children"
}
},
"required": ["uri", "line", "character", "direction"]
}
}
],
"commands": [
Expand Down
51 changes: 7 additions & 44 deletions resources/instruments/javaLspContext.instructions.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,14 @@
---
description: Unconditionally loaded for all Java projects. Provides Java LSP tools (lsp_java_*) for compiler-accurate code navigation — significantly faster and more precise than grep_search, search_subagent, or read_file for locating Java symbols, callers, implementations, and types.
applyTo: '*'
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.
applyTo: '**/*.java'
---

# Java LSP Tools — Mandatory Initialization
For Java files, two compiler-accurate `lsp_java_*` tools are available and return structured results in ~50 tokens vs ~500+ from generic search:

This workspace contains Java code. You have access to 6 compiler-accurate LSP tools that are **faster and more precise** than generic search for Java code navigation. These tools return structured results in ~20-100 tokens vs ~500-3000 tokens from grep_search, with zero false positives.
- `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

## Step 1: Load Tools (REQUIRED — do this FIRST)
These are deferred tools. Load them with `tool_search_tool_regex` using pattern `lsp_java_` before first use.

Before ANY operation, load all 6 tools by calling `tool_search_tool_regex` **twice** (the API returns at most 5 tools per call):

**Call 1** — basic navigation tools:
```
lsp_java_findSymbol|lsp_java_getFileStructure|lsp_java_getFileImports
```

**Call 2** — hierarchy and type tools:
```
lsp_java_getCallHierarchy|lsp_java_getTypeHierarchy|lsp_java_getTypeAtPosition
```

All 6 tools must be returned across the two calls. If any are missing, retry that call once. Do NOT use `grep_search`, `read_file`, `semantic_search`, `search_subagent`, or `runSubagent` on `.java` files until all tools are loaded.

## Step 2: Always Prefer LSP Tools for Java

| Task | ✅ Use | ❌ Not |
|---|---|---|
| Find class/method/field definition | `lsp_java_findSymbol` | `grep_search`, `semantic_search`, `search_subagent` |
| See file outline (methods, fields) | `lsp_java_getFileStructure` | `read_file` full scan |
| Find all callers of a method | `lsp_java_getCallHierarchy("incoming")` | `grep_search`, `search_subagent` |
| Find all implementations | `lsp_java_getTypeHierarchy("subtypes")` | `grep_search`, `search_subagent` |
| Resolve var/lambda/generic type | `lsp_java_getTypeAtPosition` | Guessing from code |
| Check imports | `lsp_java_getFileImports` | `read_file` first lines |
| Explore Java codebase structure | `lsp_java_*` tools above | `search_subagent`, `runSubagent` |

**Keep using `grep_search`** for: non-Java files (xml, yaml, gradle), string literals, comments.

**Self-check**: Before every `.java` operation, ask: "Is there a `lsp_java_*` tool for this?" If yes, use it instead of `grep_search`, `search_subagent`, or `runSubagent`.

## Typical Workflow

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

## Fallback

- `findSymbol` returns empty → retry with shorter keyword, then fall back to `grep_search`
- Path error → use `findSymbol` to discover correct path first
- Tool error / jdtls not ready → fall back to `read_file` + `grep_search`, don't retry more than once
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.

98 changes: 23 additions & 75 deletions resources/skills/java-lsp-tools/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,93 +1,41 @@
---
name: java-lsp-tools
description: Compiler-accurate Java code intelligence tools powered by the Java Language Server. ALWAYS load this skill when the workspace contains Java, Maven (pom.xml), or Gradle (build.gradle) projects. Use these tools to find symbol definitions, get type/call hierarchies, resolve types, inspect file outlines, and check imports in Java source files. Prefer over grep_search or read_file for any Java code navigation, understanding, debugging, or refactoring task.
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.
---

# Java LSP Tools

Compiler-accurate Java code intelligence via the Java Language Server (jdtls). These 6 tools provide structured, low-token answers that are more precise than `grep_search` or `read_file` for Java code.

## Activation

These tools are **deferred** and must be discovered before first use. Activate all 6 tools at once with `tool_search_tool_regex` using pattern:

`lsp_java_findSymbol|lsp_java_getFileStructure|lsp_java_getCallHierarchy|lsp_java_getTypeHierarchy|lsp_java_getTypeAtPosition|lsp_java_getFileImports`

You only need to do this **once per session**.

## When to Replace grep_search

For Java source files, **always prefer these tools over generic alternatives**:

| You're doing... | Use instead | Why |
|---|---|---|
| Find where a class/method is defined | `lsp_java_findSymbol` | ~60 tokens vs ~500 for grep (no comment/import noise) |
| Find all callers of a method | `lsp_java_getCallHierarchy("incoming")` | ~80 tokens vs ~3000 for grep (precise call sites only) |
| Find all implementations of an interface | `lsp_java_getTypeHierarchy("subtypes")` | ~60 tokens vs ~1000 for grep |
| Check a `var`/lambda/generic type | `lsp_java_getTypeAtPosition` | ~20 tokens vs guessing wrong |
| Search in non-Java files (xml, yaml, gradle) | Keep using `grep_search` | lsp_java_* tools only work on Java source |
| Search for string literals or comments | Keep using `grep_search` | lsp_java_* tools return symbol definitions only |

**Rule of thumb**: If you're searching for a Java symbol name in `.java` files, there is almost always a `lsp_java_*` tool that returns more precise results with fewer tokens than `grep_search`.

## Anti-patterns (Avoid these)

❌ **Don't**: Use `grep_search("decodeLbs")` to find who calls `decodeLbs()`
- Returns 8+ matches including declaration, comments, imports → ~3000 output tokens

✅ **Do**: Use `lsp_java_getCallHierarchy(uri, line, char, "incoming")`
- Returns only actual call sites → ~80 output tokens

❌ **Don't**: Use `grep_search("class.*extends BaseDecoder")` to find subclasses
✅ **Do**: Use `lsp_java_getTypeHierarchy(uri, line, char, "subtypes")`

❌ **Don't**: Read entire 1000+ line file to understand its structure
✅ **Do**: Use `lsp_java_getFileStructure(uri)` first, then `read_file` on specific line ranges
Two compiler-accurate tools backed by the Java Language Server (jdtls). They return structured JSON with fewer tokens than `grep_search` or `read_file`.

## Tools

All tools accept **workspace-relative paths** (e.g. `src/main/java/com/example/MyClass.java`) or full file URIs. All return structured JSON, each response < 200 tokens.

### `lsp_java_getFileStructure`
Get hierarchical outline (classes, methods, fields) with line ranges.
Input: `{ uri }` → Output: symbol tree with `[L start-end]` ranges (~100 tokens)

### `lsp_java_findSymbol`
Search for symbol definitions by name across the workspace. Supports partial/fuzzy matching.
Input: `{ query }` → Output: up to 20 results with `{ name, kind, location }` (~60 tokens)
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

### `lsp_java_getFileImports`
Get all imports classified by source (jdk/project/external).
Input: `{ uri }` → Output: classified import list (~80 tokens)

### `lsp_java_getTypeAtPosition`
Get compiler-resolved type signature at a specific position.
Input: `{ uri, line, character }` (0-based) → Output: fully resolved type (~20 tokens)

### `lsp_java_getCallHierarchy`
Find all callers (incoming) or callees (outgoing) of a method.
Input: `{ uri, line, character, direction }` (0-based, direction: `"incoming"` | `"outgoing"`) → Output: list of `{ name, detail, location }` (~80 tokens)
### `lsp_java_getFileStructure`
Get hierarchical outline of a Java file (classes, methods, fields) with line ranges.
- Input: `{ uri }` — workspace-relative path or full URI
- 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

### `lsp_java_getTypeHierarchy`
Find supertypes or subtypes/implementors of a type.
Input: `{ uri, line, character, direction }` (0-based, direction: `"supertypes"` | `"subtypes"`) → Output: list of `{ name, kind, location }` (~60 tokens)
## When to Use

## Common Workflows
| 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 |
| Search non-Java files (xml, gradle) | `grep_search` | lsp tools |
| Search string literals or comments | `grep_search` | lsp tools |

Most tasks follow the pattern: **findSymbol → getFileStructure → targeted tool**.
## Typical Workflow

| Scenario | Workflow | Trigger |
|---|---|---|
| Debug a bug | `findSymbol` → `getFileStructure` → `read_file` (buggy method) → **`getCallHierarchy("incoming")`** → `read_file` (caller context) | When you found the buggy method and need to know ALL callers |
| Analyze impact | `findSymbol` → `getFileStructure` → `getCallHierarchy("incoming")` | Before editing a method, check who depends on it |
| Understand inheritance | `findSymbol` → `getTypeHierarchy("subtypes")` | When you see a base class and need all implementations |
| Check dependencies | `getFileImports` → `findSymbol` (dependency) → `getFileStructure` | When understanding external library usage |
| Resolve type ambiguity | `getFileStructure` → `getTypeAtPosition` | When you see `var`, generics, or lambda and need exact type |
**findSymbol → getFileStructure → read_file (specific lines only)**

## Fallback

- **`lsp_java_findSymbol` returns empty**:
- Symbol may not exist yet → switch to `read_file` + `grep_search` to confirm, then create it
- Spelling/query too specific → retry once with a shorter keyword (e.g. `"UserSvc"` instead of `"UserServiceImpl"`)
- **Path error** (e.g. "Unable to resolve nonexistent file"): Use `lsp_java_findSymbol` to discover the correct file path first, then retry.
- **Tool error / empty result** (jdtls not ready, file not in project): Fall back to `read_file` + `grep_search`. Don't retry more than once.
- `findSymbol` returns empty → retry with shorter keyword, 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
Loading
Loading