Skip to content

Commit f635233

Browse files
committed
Check in stubbed out smart select support for js/ts
For microsoft/TypeScript#29071 This require upstream TS support. Check in experimental support so that TS team can test the ux of this feature
1 parent aaee57e commit f635233

File tree

4 files changed

+71
-0
lines changed

4 files changed

+71
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as vscode from 'vscode';
7+
import * as Proto from '../protocol';
8+
import { ITypeScriptServiceClient } from '../typescriptService';
9+
import API from '../utils/api';
10+
import { VersionDependentRegistration } from '../utils/dependentRegistration';
11+
import * as typeConverters from '../utils/typeConverters';
12+
13+
class SmartSelection implements vscode.SelectionRangeProvider {
14+
public static readonly minVersion = API.v350;
15+
16+
public constructor(
17+
private readonly client: ITypeScriptServiceClient
18+
) { }
19+
20+
public async provideSelectionRanges(
21+
document: vscode.TextDocument,
22+
positions: vscode.Position[],
23+
token: vscode.CancellationToken,
24+
): Promise<vscode.SelectionRange[] | undefined> {
25+
const file = this.client.toOpenedFilePath(document);
26+
if (!file) {
27+
return undefined;
28+
}
29+
30+
const args: Proto.FileRequestArgs & { locations: Proto.Location[] } = {
31+
file,
32+
locations: positions.map(typeConverters.Position.toLocation)
33+
};
34+
const response = await this.client.execute('selectionRange', args, token);
35+
if (response.type !== 'response' || !response.body) {
36+
return undefined;
37+
}
38+
return response.body.map(SmartSelection.convertSelectionRange);
39+
}
40+
41+
private static convertSelectionRange(
42+
selectionRange: Proto.SelectionRange
43+
): vscode.SelectionRange {
44+
return new vscode.SelectionRange(
45+
typeConverters.Range.fromTextSpan(selectionRange.textSpan),
46+
selectionRange.parent ? SmartSelection.convertSelectionRange(selectionRange.parent) : undefined,
47+
);
48+
}
49+
}
50+
51+
export function register(
52+
selector: vscode.DocumentSelector,
53+
client: ITypeScriptServiceClient,
54+
) {
55+
return new VersionDependentRegistration(client, SmartSelection.minVersion, () =>
56+
vscode.languages.registerSelectionRangeProvider(selector, new SmartSelection(client)));
57+
}

extensions/typescript-language-features/src/languageProvider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export default class LanguageProvider extends Disposable {
7373
this._register((await import('./features/references')).register(selector, this.client));
7474
this._register((await import('./features/referencesCodeLens')).register(selector, this.description.id, this.client, cachedResponse));
7575
this._register((await import('./features/rename')).register(selector, this.client, this.fileConfigurationManager));
76+
this._register((await import('./features/smartSelect')).register(selector, this.client));
7677
this._register((await import('./features/signatureHelp')).register(selector, this.client));
7778
this._register((await import('./features/tagClosing')).register(selector, this.description.id, this.client));
7879
this._register((await import('./features/typeDefinitions')).register(selector, this.client));

extensions/typescript-language-features/src/typescriptService.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ import { TypeScriptServiceConfiguration } from './utils/configuration';
1111
import Logger from './utils/logger';
1212
import { PluginManager } from './utils/plugins';
1313

14+
declare module './protocol' {
15+
interface SelectionRange {
16+
textSpan: Proto.TextSpan;
17+
parent?: SelectionRange;
18+
}
19+
20+
interface SelectionRangeResponse extends Proto.Response {
21+
body?: ReadonlyArray<SelectionRange>;
22+
}
23+
}
24+
1425
export namespace ServerResponse {
1526

1627
export class Cancelled {
@@ -54,6 +65,7 @@ export interface TypeScriptRequestTypes {
5465
'quickinfo': [Proto.FileLocationRequestArgs, Proto.QuickInfoResponse];
5566
'references': [Proto.FileLocationRequestArgs, Proto.ReferencesResponse];
5667
'rename': [Proto.RenameRequestArgs, Proto.RenameResponse];
68+
'selectionRange': [Proto.FileRequestArgs & { locations: Proto.Location[] }, Proto.SelectionRangeResponse];
5769
'signatureHelp': [Proto.SignatureHelpRequestArgs, Proto.SignatureHelpResponse];
5870
'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse];
5971
}

extensions/typescript-language-features/src/utils/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default class API {
3636
public static readonly v330 = API.fromSimpleString('3.3.0');
3737
public static readonly v333 = API.fromSimpleString('3.3.3');
3838
public static readonly v340 = API.fromSimpleString('3.4.0');
39+
public static readonly v350 = API.fromSimpleString('3.5.0');
3940

4041

4142
public static fromVersionString(versionString: string): API {

0 commit comments

Comments
 (0)