mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-20 02:08:47 +00:00
ts-codelens: implementations for overrides + test
This commit is contained in:
@@ -218,6 +218,12 @@
|
||||
"description": "%typescript.implementationsCodeLens.showOnInterfaceMethods%",
|
||||
"scope": "window"
|
||||
},
|
||||
"typescript.implementationsCodeLens.showOnClassMethods": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%typescript.implementationsCodeLens.showOnClassMethods.desc%",
|
||||
"scope": "window"
|
||||
},
|
||||
"typescript.reportStyleChecksAsWarnings": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
"typescript.referencesCodeLens.showOnAllFunctions": "Enable/disable references CodeLens on all functions in TypeScript files.",
|
||||
"typescript.implementationsCodeLens.enabled": "Enable/disable implementations CodeLens. This CodeLens shows the implementers of an interface.",
|
||||
"typescript.implementationsCodeLens.showOnInterfaceMethods": "Enable/disable implementations CodeLens on interface methods.",
|
||||
"typescript.implementationsCodeLens.showOnClassMethods": "Enable/disable showing 'implementations' CodeLens above class methods.",
|
||||
"typescript.openTsServerLog.title": "Open TS Server log",
|
||||
"typescript.restartTsServer": "Restart TS Server",
|
||||
"typescript.selectTypeScriptVersion.title": "Select TypeScript Version...",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"',
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user