Lombok ExtMethod AutoComplete
English | 中文
A VS Code extension that provides intelligent auto-completion for Lombok @ExtensionMethod static methods in Java files.
When you annotate a class with @ExtensionMethod and call a method on an expression, Lombok treats the first parameter of the utility method as the receiver — this extension makes those methods appear in the completion popup just like native methods.
Features
- Auto-completion — suggests
@ExtensionMethod static methods when typing . or .prefix on an expression
- Type filtering — only compatible methods (matching the receiver's type) are suggested, with fallback to local variable declaration parsing when Hover Provider fails
- Prefix filtering — further narrows candidates as you type characters after the dot
- Snippet insertion — parameters are inserted with named placeholders (e.g.,
${1:int_maxWidth}), automatically omitting the receiver parameter
- Generic type support — methods with type parameters like
<T> are properly parsed; generic parameters are treated as compatible with any type
- Workspace and JAR sources — methods from both local source files and JAR dependencies are resolved
- Multi-stage source resolution — definition provider →
findFiles → path derivation → same-directory search, with graceful fallback
- Chained calls —
expr.method1(arg).method2(). chains are fully supported; each step's type is resolved via JDT LS hover, with fallback to return-type inference from the cached method list
- Live cache invalidation — when a workspace source file is saved, its cached methods are automatically cleared; TTL 10 minutes
Installation
Search for Lombok ExtMethod AutoComplete in the VS Code extension marketplace, or run:
ext install JensenQi.lombok-extmethod-autocomplete
Usage
- Add Lombok to your project (Maven/Gradle)
- Annotate a class with
@ExtensionMethod:
import lombok.experimental.ExtensionMethod;
import org.apache.commons.lang3.StringUtils;
@ExtensionMethod(StringUtils.class)
public class MyService {
public void process(String input) {
// Type "." or ".prefix" after the expression to see extension methods
input. ← shows abbreviate, capitalize, etc.
input.abbr ← shows abbreviate(int maxWidth), etc.
// Tab to insert snippet: methodName(argType_argName)
x.abbreviate(int_maxWidth)
}
}
Multiple extension classes are supported:
@ExtensionMethod({StringUtils.class, ObjectUtils.class, MyUtils.class})
How It Works
Annotation Parsing (annotationResolver.ts) — scans the current document for @ExtensionMethod annotations using regex, resolves simple class names to FQN via imports and package declaration. Wildcard imports (import foo.*) cannot be resolved — use explicit imports for extension classes.
Source Resolution (jdtlsHelper.ts) — for each FQN, searches source in priority order:
- Calls
vscode.executeDefinitionProvider to trigger JDT LS go-to-definition. The returned URI is either:
- JAR class:
jdt://contents/... virtual file URI — opens decompiled source (FernFlower) via openTextDocument
- Workspace class:
file://path/to/... — reads the source file directly
- Falls back to
workspace.findFiles if the definition provider fails
- Falls back to path derivation from the reference document's package path
- Finally tries the same directory as the reference document
Method Parsing (jdtlsHelper.ts) — extracts public static method signatures (name, parameter types, return type) from source using regex; parameter names are stripped; constructors and lambda methods are skipped.
Type Filtering (completionProvider.ts) — determines the receiver expression's type:
- Prefers
vscode.executeHoverProvider to get the expression type
- Falls back to
parseLocalVarType (regex-based local variable declaration parser) when Hover Provider fails
- Only methods whose first parameter is compatible with the expression type are kept; generic type parameters (single letters like
T) are treated as compatible with any type
- Also filters by characters typed after the dot (prefix filtering)
Completion — each method becomes a CompletionItem (isIncomplete: true to retrigger on each keystroke), label shows methodName(args...), the first parameter (receiver) is dropped from the snippet since Lombok passes the target expression as the first argument automatically.
Module Structure
| Module |
Responsibility |
extension.ts |
Entry point, registers CompletionProvider, commands, status bar |
completionProvider.ts |
Core completion logic: type filtering, prefix filtering, snippet generation |
annotationResolver.ts |
Parses @ExtensionMethod annotations and import statements |
jdtlsHelper.ts |
Source retrieval via JDT LS, static method signature parsing, file search fallback |
cache.ts |
Generic TTL cache for parsed method lists |
logger.ts |
Debug logging controlled by lombokExtensionMethod.debugEnabled |
Commands
These commands are only visible in the command palette when lombokExtensionMethod.debugEnabled is true.
| Command |
Description |
Lombok EM: Resolve type at cursor |
Show which @ExtensionMethod classes are found |
Lombok EM: Clear method cache |
Clear the 10-minute method cache |
Lombok EM: Show parsed methods |
Print all parsed methods to the output channel |
Lombok EM: Show jdt.ls sortText |
Print jdt.ls completion sortText to the output channel |
Configuration
| Setting |
Type |
Default |
Description |
lombokExtensionMethod.debugEnabled |
boolean |
false |
Enable debug logging to "Lombok Extension Method" output channel |
Requirements
Limitations
- Receiver type filtering relies on VS Code's Hover Provider. If neither hover nor local variable parsing can determine the type, all extension methods are shown (no filtering).
- Wildcard imports (
import some.package.*) are not supported for class resolution — use explicit imports for extension classes.
- Complex generic bounds (
<T extends Comparable<T>>) may not parse correctly in method signatures.
Development
npm install
npm run compile
npx vitest run # run unit tests
npx vsce package # package .vsix
Launch the extension in VS Code by pressing F5 with the project open in a separate window.
License
Apache2.0