mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-02 06:21:50 +01:00
Update tests and small tweaks
This commit is contained in:
@@ -26,7 +26,7 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
|
||||
this._register(
|
||||
vscode.workspace.onDidChangeConfiguration(evt => {
|
||||
if (evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnInterfaceMethods`) ||
|
||||
evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnClassMethods`)) {
|
||||
evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnAllClassMethods`)) {
|
||||
this.changeEmitter.fire();
|
||||
}
|
||||
})
|
||||
@@ -70,12 +70,9 @@ 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: 'editor.action.showReferences',
|
||||
command: locations.length ? 'editor.action.showReferences' : '',
|
||||
arguments: [codeLens.document, codeLens.range.start, locations]
|
||||
};
|
||||
}
|
||||
@@ -93,33 +90,15 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
|
||||
): vscode.Range | undefined {
|
||||
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);
|
||||
}
|
||||
|
||||
// Keep the interface node itself so we enter children
|
||||
// Always show on interfaces
|
||||
if (item.kind === PConst.Kind.interface) {
|
||||
return getSymbolRange(document, item);
|
||||
}
|
||||
|
||||
// Interface members (behind existing setting)
|
||||
// Always show on abstract classes/properties
|
||||
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.class ||
|
||||
item.kind === PConst.Kind.method ||
|
||||
item.kind === PConst.Kind.memberVariable ||
|
||||
item.kind === PConst.Kind.memberGetAccessor ||
|
||||
item.kind === PConst.Kind.memberSetAccessor) &&
|
||||
@@ -128,12 +107,25 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
|
||||
return getSymbolRange(document, item);
|
||||
}
|
||||
|
||||
// Class methods (behind new setting; default off)
|
||||
// If configured, show interface members
|
||||
if (
|
||||
item.kind === PConst.Kind.method &&
|
||||
parent?.kind === PConst.Kind.interface &&
|
||||
cfg.get<boolean>('implementationsCodeLens.showOnInterfaceMethods', false)
|
||||
) {
|
||||
return getSymbolRange(document, item);
|
||||
}
|
||||
|
||||
|
||||
// If configured show on all class methods
|
||||
if (
|
||||
item.kind === PConst.Kind.method &&
|
||||
parent?.kind === PConst.Kind.class &&
|
||||
cfg.get<boolean>('implementationsCodeLens.showOnClassMethods', false)
|
||||
cfg.get<boolean>('implementationsCodeLens.showOnAllClassMethods', false)
|
||||
) {
|
||||
if (/\bprivate\b/.test(item.kindModifiers ?? '')) {
|
||||
return undefined;
|
||||
}
|
||||
return getSymbolRange(document, item);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,42 +5,164 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { joinLines, withRandomFileEditor } from "../testUtils";
|
||||
import { disposeAll } from '../../utils/dispose';
|
||||
import { joinLines, withRandomFileEditor } from '../testUtils';
|
||||
import { updateConfig, VsCodeConfiguration } from './referencesCodeLens.test';
|
||||
|
||||
suite("TypeScript Implementations CodeLens", () => {
|
||||
test("should show implementations code lens for overridden methods", async () => {
|
||||
const Config = {
|
||||
referencesCodeLens: 'typescript.referencesCodeLens.enabled',
|
||||
implementationsCodeLens: 'typescript.implementationsCodeLens.enabled',
|
||||
showOnAllClassMethods: 'typescript.implementationsCodeLens.showOnAllClassMethods',
|
||||
};
|
||||
|
||||
function getCodeLenses(doc: vscode.TextDocument) {
|
||||
return vscode.commands.executeCommand<vscode.CodeLens[]>('vscode.executeCodeLensProvider', doc.uri);
|
||||
}
|
||||
|
||||
suite('TypeScript Implementations CodeLens', () => {
|
||||
const configDefaults = Object.freeze<VsCodeConfiguration>({
|
||||
[Config.referencesCodeLens]: false,
|
||||
[Config.implementationsCodeLens]: true,
|
||||
[Config.showOnAllClassMethods]: false,
|
||||
});
|
||||
|
||||
const _disposables: vscode.Disposable[] = [];
|
||||
let oldConfig: { [key: string]: any } = {};
|
||||
|
||||
setup(async () => {
|
||||
// the tests assume that typescript features are registered
|
||||
await vscode.extensions.getExtension('vscode.typescript-language-features')!.activate();
|
||||
|
||||
// Save off config and apply defaults
|
||||
oldConfig = await updateConfig(configDefaults);
|
||||
});
|
||||
|
||||
teardown(async () => {
|
||||
disposeAll(_disposables);
|
||||
|
||||
// Restore config
|
||||
await updateConfig(oldConfig);
|
||||
|
||||
return vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
});
|
||||
|
||||
test('Should show on interfaces and abstract classes', async () => {
|
||||
await withRandomFileEditor(
|
||||
joinLines(
|
||||
"abstract class A {",
|
||||
" foo() {}",
|
||||
"}",
|
||||
"class B extends A {",
|
||||
" foo() {}",
|
||||
"}",
|
||||
'interface IFoo {}',
|
||||
'class Foo implements IFoo {}',
|
||||
'abstract class AbstractBase {}',
|
||||
'class Concrete extends AbstractBase {}'
|
||||
),
|
||||
"ts",
|
||||
async (editor: vscode.TextEditor, doc: vscode.TextDocument) => {
|
||||
assert.strictEqual(
|
||||
editor.document,
|
||||
doc,
|
||||
"Editor and document should match",
|
||||
);
|
||||
'ts',
|
||||
async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => {
|
||||
const lenses = await getCodeLenses(doc);
|
||||
assert.strictEqual(lenses?.length, 2);
|
||||
|
||||
const lenses = await vscode.commands.executeCommand<vscode.CodeLens[]>(
|
||||
"vscode.executeCodeLensProvider",
|
||||
doc.uri,
|
||||
);
|
||||
assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected interface IFoo to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[1].range.start.line, 2, 'Expected abstract class AbstractBase to have a CodeLens');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const fooLens = lenses?.find((lens) =>
|
||||
doc.getText(lens.range).includes("foo"),
|
||||
);
|
||||
test('Should show on abstract methods, properties, and getters', async () => {
|
||||
await withRandomFileEditor(
|
||||
joinLines(
|
||||
'abstract class Base {',
|
||||
' abstract method(): void;',
|
||||
' abstract property: string;',
|
||||
' abstract get getter(): number;',
|
||||
'}',
|
||||
'class Derived extends Base {',
|
||||
' method() {}',
|
||||
' property = "test";',
|
||||
' get getter() { return 42; }',
|
||||
'}',
|
||||
),
|
||||
'ts',
|
||||
async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => {
|
||||
const lenses = await getCodeLenses(doc);
|
||||
assert.strictEqual(lenses?.length, 4);
|
||||
|
||||
assert.ok(fooLens, "Expected a CodeLens above foo()");
|
||||
assert.match(
|
||||
fooLens!.command?.title ?? "",
|
||||
/1 implementation/,
|
||||
'Expected lens to show "1 implementation"',
|
||||
);
|
||||
assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected abstract class to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[1].range.start.line, 1, 'Expected abstract method to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[2].range.start.line, 2, 'Expected abstract property to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[3].range.start.line, 3, 'Expected abstract getter to have a CodeLens');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('Should not show implementations on methods by default', async () => {
|
||||
await withRandomFileEditor(
|
||||
joinLines(
|
||||
'abstract class A {',
|
||||
' foo() {}',
|
||||
'}',
|
||||
'class B extends A {',
|
||||
' foo() {}',
|
||||
'}',
|
||||
),
|
||||
'ts',
|
||||
async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => {
|
||||
const lenses = await getCodeLenses(doc);
|
||||
assert.strictEqual(lenses?.length, 1);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('should show on all methods when showOnAllClassMethods is enabled', async () => {
|
||||
await updateConfig({
|
||||
[Config.showOnAllClassMethods]: true
|
||||
});
|
||||
|
||||
await withRandomFileEditor(
|
||||
joinLines(
|
||||
'abstract class A {',
|
||||
' foo() {}',
|
||||
'}',
|
||||
'class B extends A {',
|
||||
' foo() {}',
|
||||
'}',
|
||||
),
|
||||
'ts',
|
||||
async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => {
|
||||
const lenses = await getCodeLenses(doc);
|
||||
assert.strictEqual(lenses?.length, 3);
|
||||
|
||||
assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected class A to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[1].range.start.line, 1, 'Expected method A.foo to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[2].range.start.line, 4, 'Expected method B.foo to have a CodeLens');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('should not show on private methods when showOnAllClassMethods is enabled', async () => {
|
||||
await updateConfig({
|
||||
[Config.showOnAllClassMethods]: true
|
||||
});
|
||||
|
||||
await withRandomFileEditor(
|
||||
joinLines(
|
||||
'abstract class A {',
|
||||
' public foo() {}',
|
||||
' private bar() {}',
|
||||
' protected baz() {}',
|
||||
'}',
|
||||
'class B extends A {',
|
||||
' public foo() {}',
|
||||
' protected baz() {}',
|
||||
'}',
|
||||
),
|
||||
'ts',
|
||||
async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => {
|
||||
const lenses = await getCodeLenses(doc);
|
||||
assert.strictEqual(lenses?.length, 5);
|
||||
|
||||
assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected class A to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[1].range.start.line, 1, 'Expected method A.foo to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[2].range.start.line, 3, 'Expected method A.baz to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[3].range.start.line, 6, 'Expected method B.foo to have a CodeLens');
|
||||
assert.strictEqual(lenses?.[4].range.start.line, 7, 'Expected method B.baz to have a CodeLens');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -10,9 +10,9 @@ import { createTestEditor, wait } from '../../test/testUtils';
|
||||
import { disposeAll } from '../../utils/dispose';
|
||||
|
||||
|
||||
type VsCodeConfiguration = { [key: string]: any };
|
||||
export type VsCodeConfiguration = { [key: string]: any };
|
||||
|
||||
async function updateConfig(newConfig: VsCodeConfiguration): Promise<VsCodeConfiguration> {
|
||||
export async function updateConfig(newConfig: VsCodeConfiguration): Promise<VsCodeConfiguration> {
|
||||
const oldConfig: VsCodeConfiguration = {};
|
||||
const config = vscode.workspace.getConfiguration(undefined);
|
||||
for (const configKey of Object.keys(newConfig)) {
|
||||
|
||||
Reference in New Issue
Block a user