ts-codelens: implementations for overrides + test

This commit is contained in:
ritesh006
2025-09-09 18:02:22 +05:30
parent 05c2fd5932
commit cd5348abcd
4 changed files with 102 additions and 15 deletions

View File

@@ -25,7 +25,8 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
super(client, _cachedResponse);
this._register(
vscode.workspace.onDidChangeConfiguration(evt => {
if (evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnInterfaceMethods`)) {
if (evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnInterfaceMethods`) ||
evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnClassMethods`)) {
this.changeEmitter.fire();
}
})
@@ -69,9 +70,12 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
}
private getCommand(locations: vscode.Location[], codeLens: ReferencesCodeLens): vscode.Command | undefined {
if (!locations.length) {
return undefined;
}
return {
title: this.getTitle(locations),
command: locations.length ? 'editor.action.showReferences' : '',
command: 'editor.action.showReferences',
arguments: [codeLens.document, codeLens.range.start, locations]
};
}
@@ -87,23 +91,52 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
item: Proto.NavigationTree,
parent: Proto.NavigationTree | undefined
): vscode.Range | undefined {
if (item.kind === PConst.Kind.method && parent && parent.kind === PConst.Kind.interface && vscode.workspace.getConfiguration(this.language.id).get<boolean>('implementationsCodeLens.showOnInterfaceMethods')) {
const cfg = vscode.workspace.getConfiguration(this.language.id);
// Keep the class node itself so we enter children
if (item.kind === PConst.Kind.class) {
return getSymbolRange(document, item);
}
switch (item.kind) {
case PConst.Kind.interface:
return getSymbolRange(document, item);
case PConst.Kind.class:
case PConst.Kind.method:
case PConst.Kind.memberVariable:
case PConst.Kind.memberGetAccessor:
case PConst.Kind.memberSetAccessor:
if (item.kindModifiers.match(/\babstract\b/g)) {
return getSymbolRange(document, item);
}
break;
// Keep the interface node itself so we enter children
if (item.kind === PConst.Kind.interface) {
return getSymbolRange(document, item);
}
// Interface members (behind existing setting)
if (
item.kind === PConst.Kind.method &&
parent?.kind === PConst.Kind.interface &&
cfg.get<boolean>('implementationsCodeLens.showOnInterfaceMethods')
) {
return getSymbolRange(document, item);
}
// Skip private methods (cannot be overridden)
if (item.kind === PConst.Kind.method && /\bprivate\b/.test(item.kindModifiers ?? '')) {
return undefined;
}
// Abstract members (always show)
if (
(item.kind === PConst.Kind.method ||
item.kind === PConst.Kind.memberVariable ||
item.kind === PConst.Kind.memberGetAccessor ||
item.kind === PConst.Kind.memberSetAccessor) &&
/\babstract\b/.test(item.kindModifiers ?? '')
) {
return getSymbolRange(document, item);
}
// Class methods (behind new setting; default off)
if (
item.kind === PConst.Kind.method &&
parent?.kind === PConst.Kind.class &&
cfg.get<boolean>('implementationsCodeLens.showOnClassMethods', false)
) {
return getSymbolRange(document, item);
}
return undefined;
}
}

View File

@@ -0,0 +1,47 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as vscode from 'vscode';
import { joinLines, withRandomFileEditor } from "../testUtils";
suite("TypeScript Implementations CodeLens", () => {
test("should show implementations code lens for overridden methods", async () => {
await withRandomFileEditor(
joinLines(
"abstract class A {",
" foo() {}",
"}",
"class B extends A {",
" foo() {}",
"}",
),
"ts",
async (editor: vscode.TextEditor, doc: vscode.TextDocument) => {
assert.strictEqual(
editor.document,
doc,
"Editor and document should match",
);
const lenses = await vscode.commands.executeCommand<vscode.CodeLens[]>(
"vscode.executeCodeLensProvider",
doc.uri,
);
const fooLens = lenses?.find((lens) =>
doc.getText(lens.range).includes("foo"),
);
assert.ok(fooLens, "Expected a CodeLens above foo()");
assert.match(
fooLens!.command?.title ?? "",
/1 implementation/,
'Expected lens to show "1 implementation"',
);
},
);
});
});