Add tag closing completions

Part of #34307. Add manual completions for closing jsx tags. Requires TS 3.0
This commit is contained in:
Matt Bierner 2018-06-19 10:57:11 -07:00
parent 76f33a4ab6
commit 4d3a8ae210
4 changed files with 74 additions and 1 deletions

View file

@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api';
import { VersionDependentRegistration } from '../utils/dependentRegistration';
import * as typeConverters from '../utils/typeConverters';
class TypeScriptTagCompletion implements vscode.CompletionItemProvider {
constructor(
private readonly client: ITypeScriptServiceClient
) { }
async provideCompletionItems(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
_context: vscode.CompletionContext
): Promise<vscode.CompletionItem[] | undefined> {
const filepath = this.client.toPath(document.uri);
if (!filepath) {
return undefined;
}
const args: Proto.JsxClosingTagRequestArgs = typeConverters.Position.toFileLocationRequestArgs(filepath, position);
let body: Proto.TextInsertion | undefined = undefined;
try {
const response = await this.client.execute('jsxClosingTag', args, token);
body = response && response.body;
if (!body) {
return undefined;
}
} catch {
return undefined;
}
return [this.getCompletion(body)];
}
private getCompletion(body: Proto.TextInsertion) {
const completion = new vscode.CompletionItem(body.newText);
completion.insertText = this.getTagSnippet(body);
return completion;
}
private getTagSnippet(closingTag: Proto.TextInsertion): vscode.SnippetString {
const snippet = new vscode.SnippetString();
snippet.appendPlaceholder('', 0);
snippet.appendText(closingTag.newText);
return snippet;
}
}
export function register(
selector: vscode.DocumentSelector,
client: ITypeScriptServiceClient,
) {
return new VersionDependentRegistration(client, API.v300, () =>
vscode.languages.registerCompletionItemProvider(selector,
new TypeScriptTagCompletion(client),
'>'));
}

View file

@ -91,6 +91,7 @@ export default class LanguageProvider {
this.disposables.push((await import('./features/referencesCodeLens')).register(selector, this.description.id, this.client, cachedResponse));
this.disposables.push((await import('./features/rename')).register(selector, this.client));
this.disposables.push((await import('./features/signatureHelp')).register(selector, this.client));
this.disposables.push((await import('./features/tagCompletion')).register(selector, this.client));
this.disposables.push((await import('./features/typeDefinitions')).register(selector, this.client));
this.disposables.push((await import('./features/workspaceSymbols')).register(this.client, this.description.modeIds));
}

View file

@ -1,2 +1,2 @@
import * as Proto from 'typescript/lib/protocol';
export = Proto;
export = Proto;

View file

@ -11,6 +11,11 @@ import { TypeScriptServiceConfiguration } from './utils/configuration';
import Logger from './utils/logger';
import BufferSyncSupport from './features/bufferSyncSupport';
declare module './protocol' {
export type JsxClosingTagRequestArgs = any;
export type JsxClosingTagResponse = any;
}
export interface ITypeScriptServiceClient {
/**
* Convert a resource (VS Code) to a normalized path (TypeScript).
@ -78,6 +83,7 @@ export interface ITypeScriptServiceClient {
execute(command: 'organizeImports', args: Proto.OrganizeImportsRequestArgs, token?: CancellationToken): Promise<Proto.OrganizeImportsResponse>;
execute(command: 'getOutliningSpans', args: Proto.FileRequestArgs, token: CancellationToken): Promise<Proto.OutliningSpansResponse>;
execute(command: 'getEditsForFileRename', args: Proto.GetEditsForFileRenameRequestArgs): Promise<Proto.GetEditsForFileRenameResponse>;
execute(command: 'jsxClosingTag', args: Proto.JsxClosingTagRequestArgs, token: CancellationToken): Promise<Proto.JsxClosingTagResponse>;
execute(command: string, args: any, expectedResult: boolean | CancellationToken, token?: CancellationToken): Promise<any>;
executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: CancellationToken): Promise<any>;