diff --git a/extensions/typescript-language-features/src/features/bufferSyncSupport.ts b/extensions/typescript-language-features/src/features/bufferSyncSupport.ts index f46c5e4c431d367a007eb73f70bd47c6b3e6ce9f..ddbccd3a27de1118841f8500f8ba409d2557b76f 100644 --- a/extensions/typescript-language-features/src/features/bufferSyncSupport.ts +++ b/extensions/typescript-language-features/src/features/bufferSyncSupport.ts @@ -63,7 +63,7 @@ class SyncedBuffer { } } - this.client.execute('open', args, false); + this.client.executeWithoutWaitingForResponse('open', args); } public get resource(): vscode.Uri { @@ -91,7 +91,7 @@ class SyncedBuffer { const args: Proto.FileRequestArgs = { file: this.filepath }; - this.client.execute('close', args, false); + this.client.executeWithoutWaitingForResponse('close', args); } public onContentChanged(events: vscode.TextDocumentContentChangeEvent[]): void { @@ -100,7 +100,7 @@ class SyncedBuffer { insertString: text, ...typeConverters.Range.toFormattingRequestArgs(this.filepath, range) }; - this.client.execute('change', args, false); + this.client.executeWithoutWaitingForResponse('change', args); } } } diff --git a/extensions/typescript-language-features/src/features/completions.ts b/extensions/typescript-language-features/src/features/completions.ts index 5f7ab35763669c360d27891e86b26b071368d690..e1eb9121f13d503a650f678e44a8d0c06a318dfb 100644 --- a/extensions/typescript-language-features/src/features/completions.ts +++ b/extensions/typescript-language-features/src/features/completions.ts @@ -16,6 +16,7 @@ import * as typeConverters from '../utils/typeConverters'; import TypingsStatus from '../utils/typingsStatus'; import FileConfigurationManager from './fileConfigurationManager'; import { memoize } from '../utils/memoize'; +import { nulToken } from '../utils/cancellation'; const localize = nls.loadMessageBundle(); @@ -205,7 +206,7 @@ class ApplyCompletionCodeActionCommand implements Command { } if (codeActions.length === 1) { - return applyCodeAction(this.client, codeActions[0]); + return applyCodeAction(this.client, codeActions[0], nulToken); } interface MyQuickPickItem extends vscode.QuickPickItem { @@ -230,7 +231,7 @@ class ApplyCompletionCodeActionCommand implements Command { if (!action) { return false; } - return applyCodeAction(this.client, action); + return applyCodeAction(this.client, action, nulToken); } } @@ -384,7 +385,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider item.additionalTextEdits = additionalTextEdits; if (detail && item.useCodeSnippet) { - const shouldCompleteFunction = await this.isValidFunctionCompletionContext(filepath, item.position); + const shouldCompleteFunction = await this.isValidFunctionCompletionContext(filepath, item.position, token); if (shouldCompleteFunction) { item.insertText = this.snippetForFunctionCall(item, detail); } @@ -524,12 +525,13 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider private async isValidFunctionCompletionContext( filepath: string, - position: vscode.Position + position: vscode.Position, + token: vscode.CancellationToken ): Promise { // Workaround for https://github.com/Microsoft/TypeScript/issues/12677 // Don't complete function calls inside of destructive assigments or imports try { - const { body } = await this.client.execute('quickinfo', typeConverters.Position.toFileLocationRequestArgs(filepath, position)); + const { body } = await this.client.execute('quickinfo', typeConverters.Position.toFileLocationRequestArgs(filepath, position), token); switch (body && body.kind) { case 'var': case 'let': diff --git a/extensions/typescript-language-features/src/features/definitionProviderBase.ts b/extensions/typescript-language-features/src/features/definitionProviderBase.ts index 88d61f56a87f0668d24aaa0cace12a67e33aa70b..186d3e711dd0585b7be1cca7cfee5f356ad3c4b5 100644 --- a/extensions/typescript-language-features/src/features/definitionProviderBase.ts +++ b/extensions/typescript-language-features/src/features/definitionProviderBase.ts @@ -18,7 +18,7 @@ export default class TypeScriptDefinitionProviderBase { definitionType: 'definition' | 'implementation' | 'typeDefinition', document: vscode.TextDocument, position: vscode.Position, - token: vscode.CancellationToken | boolean + token: vscode.CancellationToken ): Promise { const filepath = this.client.toPath(document.uri); if (!filepath) { diff --git a/extensions/typescript-language-features/src/features/definitions.ts b/extensions/typescript-language-features/src/features/definitions.ts index 99b9c36624768617751067a4e66c9c431791c7c0..6e260d5d089f6fc612a71f0ce0d01fcff25650e1 100644 --- a/extensions/typescript-language-features/src/features/definitions.ts +++ b/extensions/typescript-language-features/src/features/definitions.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import * as Proto from '../protocol'; import { ITypeScriptServiceClient } from '../typescriptService'; import API from '../utils/api'; import * as typeConverters from '../utils/typeConverters'; @@ -20,7 +19,7 @@ export default class TypeScriptDefinitionProvider extends DefinitionProviderBase public async provideDefinition( document: vscode.TextDocument, position: vscode.Position, - token: vscode.CancellationToken | boolean + token: vscode.CancellationToken ): Promise { if (this.client.apiVersion.gte(API.v270)) { const filepath = this.client.toPath(document.uri); @@ -30,14 +29,13 @@ export default class TypeScriptDefinitionProvider extends DefinitionProviderBase const args = typeConverters.Position.toFileLocationRequestArgs(filepath, position); try { - const response = await this.client.execute('definitionAndBoundSpan', args, token); - const locations: Proto.FileSpan[] = (response && response.body && response.body.definitions) || []; - if (!locations) { + const { body } = await this.client.execute('definitionAndBoundSpan', args, token); + if (!body) { return undefined; } - const span = response.body.textSpan ? typeConverters.Range.fromTextSpan(response.body.textSpan) : undefined; - return locations + const span = body.textSpan ? typeConverters.Range.fromTextSpan(body.textSpan) : undefined; + return body.definitions .map(location => { const target = typeConverters.Location.fromTextSpan(this.client.toResource(location.file), location); return { diff --git a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts index 90587ba4925f070f2e7920f7798b28f8c93ac8fd..f7b77cb35f6a85477b6ce3609329368f0be853fa 100644 --- a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts +++ b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts @@ -59,7 +59,7 @@ export default class FileConfigurationManager { public async ensureConfigurationForDocument( document: vscode.TextDocument, - token: vscode.CancellationToken | undefined + token: vscode.CancellationToken ): Promise { const editor = vscode.window.visibleTextEditors.find(editor => editor.document.fileName === document.fileName); if (editor) { @@ -74,7 +74,7 @@ export default class FileConfigurationManager { public async ensureConfigurationOptions( document: vscode.TextDocument, options: vscode.FormattingOptions, - token: vscode.CancellationToken | undefined + token: vscode.CancellationToken ): Promise { const file = this.client.toPath(document.uri); if (!file) { diff --git a/extensions/typescript-language-features/src/features/implementations.ts b/extensions/typescript-language-features/src/features/implementations.ts index c2627a352440de0d4e971489010ed8043a4361c3..d750587ea8d95a21778a98e25d34df90ae1af540 100644 --- a/extensions/typescript-language-features/src/features/implementations.ts +++ b/extensions/typescript-language-features/src/features/implementations.ts @@ -10,7 +10,7 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import DefinitionProviderBase from './definitionProviderBase'; class TypeScriptImplementationProvider extends DefinitionProviderBase implements vscode.ImplementationProvider { - public provideImplementation(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken | boolean): Promise { + public provideImplementation(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { return this.getSymbolLocations('implementation', document, position, token); } } diff --git a/extensions/typescript-language-features/src/features/jsDocCompletions.ts b/extensions/typescript-language-features/src/features/jsDocCompletions.ts index 49a51c9580792af1a087fac33323b12ae4c4e8c5..02eb7439d95d27ad94f1f534186a936473644e74 100644 --- a/extensions/typescript-language-features/src/features/jsDocCompletions.ts +++ b/extensions/typescript-language-features/src/features/jsDocCompletions.ts @@ -161,9 +161,13 @@ class TryCompleteJsDocCommand implements Command { public static getSnippetTemplate(client: ITypeScriptServiceClient, file: string, position: vscode.Position): Promise { const args = typeConverters.Position.toFileLocationRequestArgs(file, position); + const tokenSource = new vscode.CancellationTokenSource(); return Promise.race([ - client.execute('docCommentTemplate', args), - new Promise((_, reject) => setTimeout(reject, 250)) + client.execute('docCommentTemplate', args, tokenSource.token), + new Promise((_, reject) => setTimeout(() => { + tokenSource.cancel(); + reject(); + }, 250)) ]).then((res: Proto.DocCommandTemplateResponse) => { if (!res || !res.body) { return undefined; diff --git a/extensions/typescript-language-features/src/features/organizeImports.ts b/extensions/typescript-language-features/src/features/organizeImports.ts index 2803d645d0a8a1c55e743940c523bd17c1ba6d0a..302da37e8fe549295efd15cbcaca17be9977410d 100644 --- a/extensions/typescript-language-features/src/features/organizeImports.ts +++ b/extensions/typescript-language-features/src/features/organizeImports.ts @@ -13,6 +13,7 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import * as typeconverts from '../utils/typeConverters'; import FileConfigurationManager from './fileConfigurationManager'; import TelemetryReporter from '../utils/telemetry'; +import { nulToken } from '../utils/cancellation'; const localize = nls.loadMessageBundle(); @@ -45,7 +46,7 @@ class OrganizeImportsCommand implements Command { } } }; - const { body } = await this.client.execute('organizeImports', args); + const { body } = await this.client.execute('organizeImports', args, nulToken); const edits = typeconverts.WorkspaceEdit.fromFileCodeEdits(this.client, body); return vscode.workspace.applyEdit(edits); } diff --git a/extensions/typescript-language-features/src/features/quickFix.ts b/extensions/typescript-language-features/src/features/quickFix.ts index 00679075cf99496128e68e626a7f2ebe0d4f8e6d..78af910606b8e3ac0b21d6cd4e2942b7c730986f 100644 --- a/extensions/typescript-language-features/src/features/quickFix.ts +++ b/extensions/typescript-language-features/src/features/quickFix.ts @@ -15,6 +15,7 @@ import TelemetryReporter from '../utils/telemetry'; import * as typeConverters from '../utils/typeConverters'; import { DiagnosticsManager } from './diagnostics'; import FileConfigurationManager from './fileConfigurationManager'; +import { nulToken } from '../utils/cancellation'; const localize = nls.loadMessageBundle(); @@ -42,7 +43,7 @@ class ApplyCodeActionCommand implements Command { fixName: action.fixName }); - return applyCodeActionCommands(this.client, action.commands); + return applyCodeActionCommands(this.client, action.commands, nulToken); } } @@ -85,14 +86,14 @@ class ApplyFixAllCodeAction implements Command { }; try { - const { body } = await this.client.execute('getCombinedCodeFix', args); + const { body } = await this.client.execute('getCombinedCodeFix', args, nulToken); if (!body) { return; } const edit = typeConverters.WorkspaceEdit.fromFileCodeEdits(this.client, body.changes); await vscode.workspace.applyEdit(edit); - await applyCodeActionCommands(this.client, body.commands); + await applyCodeActionCommands(this.client, body.commands, nulToken); } catch { // noop } @@ -167,7 +168,7 @@ class SupportedCodeActionProvider { private get supportedCodeActions(): Thenable> { if (!this._supportedCodeActions) { - this._supportedCodeActions = this.client.execute('getSupportedCodeFixes', null, undefined) + this._supportedCodeActions = this.client.execute('getSupportedCodeFixes', null, nulToken) .then(response => response.body || []) .then(codes => codes.map(code => +code).filter(code => !isNaN(code))) .then(codes => new Set(codes)); diff --git a/extensions/typescript-language-features/src/features/refactor.ts b/extensions/typescript-language-features/src/features/refactor.ts index ccb5e2f12f8f47604c232e662be08964b693bf36..bdc5d4eb25e59b5aa85a3091db10f2ddd3528cf0 100644 --- a/extensions/typescript-language-features/src/features/refactor.ts +++ b/extensions/typescript-language-features/src/features/refactor.ts @@ -12,6 +12,7 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import TelemetryReporter from '../utils/telemetry'; import * as typeConverters from '../utils/typeConverters'; import FormattingOptionsManager from './fileConfigurationManager'; +import { nulToken } from '../utils/cancellation'; class ApplyRefactoringCommand implements Command { @@ -47,7 +48,7 @@ class ApplyRefactoringCommand implements Command { refactor, action }; - const { body } = await this.client.execute('getEditsForRefactor', args); + const { body } = await this.client.execute('getEditsForRefactor', args, nulToken); if (!body || !body.edits.length) { return false; } @@ -136,7 +137,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider { return undefined; } - await this.formattingOptionsManager.ensureConfigurationForDocument(document, undefined); + await this.formattingOptionsManager.ensureConfigurationForDocument(document, token); const args: Proto.GetApplicableRefactorsRequestArgs = typeConverters.Range.toFileRangeRequestArgs(file, rangeOrSelection); let refactorings: Proto.ApplicableRefactorInfo[]; diff --git a/extensions/typescript-language-features/src/features/typeDefinitions.ts b/extensions/typescript-language-features/src/features/typeDefinitions.ts index 23f8b18af3975fd8d9f76cafa0972eaedb7fc489..45d89aeaeddb7c645134308dc4dfbacb9a9347c0 100644 --- a/extensions/typescript-language-features/src/features/typeDefinitions.ts +++ b/extensions/typescript-language-features/src/features/typeDefinitions.ts @@ -10,7 +10,7 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import DefinitionProviderBase from './definitionProviderBase'; export default class TypeScriptTypeDefinitionProvider extends DefinitionProviderBase implements vscode.TypeDefinitionProvider { - public provideTypeDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken | boolean): Promise { + public provideTypeDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { return this.getSymbolLocations('typeDefinition', document, position, token); } } diff --git a/extensions/typescript-language-features/src/features/updatePathsOnRename.ts b/extensions/typescript-language-features/src/features/updatePathsOnRename.ts index ba19b8da8aa5987f15d4f10c7e3025593fde0fde..6d12999aa929ad2bcf8545dbad3c5a3eae25f63d 100644 --- a/extensions/typescript-language-features/src/features/updatePathsOnRename.ts +++ b/extensions/typescript-language-features/src/features/updatePathsOnRename.ts @@ -16,6 +16,7 @@ import { escapeRegExp } from '../utils/regexp'; import * as typeConverters from '../utils/typeConverters'; import FileConfigurationManager from './fileConfigurationManager'; import { VersionDependentRegistration } from '../utils/dependentRegistration'; +import { nulToken } from '../utils/cancellation'; const localize = nls.loadMessageBundle(); @@ -84,7 +85,7 @@ class UpdateImportsOnFileRenameHandler { // Workaround for https://github.com/Microsoft/vscode/issues/52967 // Never attempt to update import paths if the file does not contain something the looks like an export try { - const { body } = await this.client.execute('navtree', { file: newFile }); + const { body } = await this.client.execute('navtree', { file: newFile }, nulToken); const hasExport = (node: Proto.NavigationTree): boolean => { return !!node.kindModifiers.match(/\bexports?\b/g) || !!(node.childItems && node.childItems.some(hasExport)); }; @@ -229,14 +230,14 @@ class UpdateImportsOnFileRenameHandler { newFile: string, ) { const isDirectoryRename = fs.lstatSync(newFile).isDirectory(); - await this.fileConfigurationManager.ensureConfigurationForDocument(document, undefined); + await this.fileConfigurationManager.ensureConfigurationForDocument(document, nulToken); const args: Proto.GetEditsForFileRenameRequestArgs & { file: string } = { file: targetResource, oldFilePath: oldFile, newFilePath: newFile, }; - const response = await this.client.execute('getEditsForFileRename', args); + const response = await this.client.execute('getEditsForFileRename', args, nulToken); if (!response || !response.body) { return; } diff --git a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts index cea7c0a2bc4012623102b29a4ab781a5a1cb2e91..afff7001672b047f3162053e3900004f702b7cd5 100644 --- a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts +++ b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts @@ -55,7 +55,7 @@ export default class TypeScriptServiceClientHost extends Disposable { ) { super(); const handleProjectCreateOrDelete = () => { - this.client.execute('reloadProjects', null, false); + this.client.executeWithoutWaitingForResponse('reloadProjects', null); this.triggerAllDiagnostics(); }; const handleProjectChange = () => { @@ -150,7 +150,7 @@ export default class TypeScriptServiceClientHost extends Disposable { } public reloadProjects(): void { - this.client.execute('reloadProjects', null, false); + this.client.executeWithoutWaitingForResponse('reloadProjects', null); this.triggerAllDiagnostics(); } diff --git a/extensions/typescript-language-features/src/typescriptService.ts b/extensions/typescript-language-features/src/typescriptService.ts index bb6baa31915ecd169bbee0e53341f194cab09393..b31f39659fbd41c61dab1e4091708a2708852406 100644 --- a/extensions/typescript-language-features/src/typescriptService.ts +++ b/extensions/typescript-language-features/src/typescriptService.ts @@ -11,6 +11,70 @@ import { TypeScriptServiceConfiguration } from './utils/configuration'; import Logger from './utils/logger'; import { TypeScriptServerPlugin } from './utils/plugins'; +interface TypeScriptArgsMap { + 'configure': Proto.ConfigureRequestArguments; + 'quickinfo': Proto.FileLocationRequestArgs; + 'completions': Proto.CompletionsRequestArgs; + 'completionInfo': Proto.CompletionsRequestArgs; + 'completionEntryDetails': Proto.CompletionDetailsRequestArgs; + 'signatureHelp': Proto.SignatureHelpRequestArgs; + 'definition': Proto.FileLocationRequestArgs; + 'definitionAndBoundSpan': Proto.FileLocationRequestArgs; + 'implementation': Proto.FileLocationRequestArgs; + 'typeDefinition': Proto.FileLocationRequestArgs; + 'references': Proto.FileLocationRequestArgs; + 'navto': Proto.NavtoRequestArgs; + 'format': Proto.FormatRequestArgs; + 'formatonkey': Proto.FormatOnKeyRequestArgs; + 'rename': Proto.RenameRequestArgs; + 'occurrences': Proto.FileLocationRequestArgs; + 'projectInfo': Proto.ProjectInfoRequestArgs; + 'navtree': Proto.FileRequestArgs; + 'getCodeFixes': Proto.CodeFixRequestArgs; + 'getSupportedCodeFixes': null; + 'getCombinedCodeFix': Proto.GetCombinedCodeFixRequestArgs; + 'docCommentTemplate': Proto.FileLocationRequestArgs; + 'getApplicableRefactors': Proto.GetApplicableRefactorsRequestArgs; + 'getEditsForRefactor': Proto.GetEditsForRefactorRequestArgs; + 'applyCodeActionCommand': Proto.ApplyCodeActionCommandRequestArgs; + 'organizeImports': Proto.OrganizeImportsRequestArgs; + 'getOutliningSpans': Proto.FileRequestArgs; + 'getEditsForFileRename': Proto.GetEditsForFileRenameRequestArgs; + 'jsxClosingTag': Proto.JsxClosingTagRequestArgs; +} + +interface TypeScriptResultMap { + 'configure': Proto.ConfigureResponse; + 'quickinfo': Proto.QuickInfoResponse; + 'completions': Proto.CompletionsResponse; + 'completionInfo': Proto.CompletionInfoResponse; + 'completionEntryDetails': Proto.CompletionDetailsResponse; + 'signatureHelp': Proto.SignatureHelpResponse; + 'definition': Proto.DefinitionResponse; + 'definitionAndBoundSpan': Proto.DefinitionInfoAndBoundSpanReponse; + 'implementation': Proto.ImplementationResponse; + 'typeDefinition': Proto.TypeDefinitionResponse; + 'references': Proto.ReferencesResponse; + 'navto': Proto.NavtoResponse; + 'format': Proto.FormatResponse; + 'formatonkey': Proto.FormatResponse; + 'rename': Proto.RenameResponse; + 'occurrences': Proto.OccurrencesResponse; + 'projectInfo': Proto.ProjectInfoResponse; + 'navtree': Proto.NavTreeResponse; + 'getCodeFixes': Proto.GetCodeFixesResponse; + 'getSupportedCodeFixes': Proto.GetSupportedCodeFixesResponse; + 'getCombinedCodeFix': Proto.GetCombinedCodeFixResponse; + 'docCommentTemplate': Proto.DocCommandTemplateResponse; + 'getApplicableRefactors': Proto.GetApplicableRefactorsResponse; + 'getEditsForRefactor': Proto.GetEditsForRefactorResponse; + 'applyCodeActionCommand': Proto.ApplyCodeActionCommandResponse; + 'organizeImports': Proto.OrganizeImportsResponse; + 'getOutliningSpans': Proto.OutliningSpansResponse; + 'getEditsForFileRename': Proto.GetEditsForFileRenameResponse; + 'jsxClosingTag': Proto.JsxClosingTagResponse; +} + export interface ITypeScriptServiceClient { /** * Convert a resource (VS Code) to a normalized path (TypeScript). @@ -45,42 +109,17 @@ export interface ITypeScriptServiceClient { readonly logger: Logger; readonly bufferSyncSupport: BufferSyncSupport; - execute(command: 'configure', args: Proto.ConfigureRequestArguments, token?: vscode.CancellationToken): Promise; - execute(command: 'open', args: Proto.OpenRequestArgs, expectedResult: boolean, token?: vscode.CancellationToken): Promise; - execute(command: 'close', args: Proto.FileRequestArgs, expectedResult: boolean, token?: vscode.CancellationToken): Promise; - execute(command: 'change', args: Proto.ChangeRequestArgs, expectedResult: boolean, token?: vscode.CancellationToken): Promise; - execute(command: 'quickinfo', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'completions', args: Proto.CompletionsRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'completionInfo', args: Proto.CompletionsRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'completionEntryDetails', args: Proto.CompletionDetailsRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'signatureHelp', args: Proto.SignatureHelpRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'definition', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'definitionAndBoundSpan', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'implementation', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'typeDefinition', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'references', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'navto', args: Proto.NavtoRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'format', args: Proto.FormatRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'formatonkey', args: Proto.FormatOnKeyRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'rename', args: Proto.RenameRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'occurrences', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'projectInfo', args: Proto.ProjectInfoRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'reloadProjects', args: any, expectedResult: boolean, token?: vscode.CancellationToken): Promise; - execute(command: 'reload', args: Proto.ReloadRequestArgs, expectedResult: boolean, token?: vscode.CancellationToken): Promise; - execute(command: 'compilerOptionsForInferredProjects', args: Proto.SetCompilerOptionsForInferredProjectsArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'navtree', args: Proto.FileRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'getCodeFixes', args: Proto.CodeFixRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'getSupportedCodeFixes', args: null, token?: vscode.CancellationToken): Promise; - execute(command: 'getCombinedCodeFix', args: Proto.GetCombinedCodeFixRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'docCommentTemplate', args: Proto.FileLocationRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'getApplicableRefactors', args: Proto.GetApplicableRefactorsRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'getEditsForRefactor', args: Proto.GetEditsForRefactorRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'applyCodeActionCommand', args: Proto.ApplyCodeActionCommandRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'organizeImports', args: Proto.OrganizeImportsRequestArgs, token?: vscode.CancellationToken): Promise; - execute(command: 'getOutliningSpans', args: Proto.FileRequestArgs, token: vscode.CancellationToken): Promise; - execute(command: 'getEditsForFileRename', args: Proto.GetEditsForFileRenameRequestArgs): Promise; - execute(command: 'jsxClosingTag', args: Proto.JsxClosingTagRequestArgs, token: vscode.CancellationToken): Promise; - execute(command: string, args: any, expectedResult: boolean | vscode.CancellationToken, token?: vscode.CancellationToken): Promise; + execute( + command: K, + args: TypeScriptArgsMap[K], + token: vscode.CancellationToken + ): Promise; + + executeWithoutWaitingForResponse(command: 'open', args: Proto.OpenRequestArgs): void; + executeWithoutWaitingForResponse(command: 'close', args: Proto.FileRequestArgs): void; + executeWithoutWaitingForResponse(command: 'change', args: Proto.ChangeRequestArgs): void; + executeWithoutWaitingForResponse(command: 'compilerOptionsForInferredProjects', args: Proto.SetCompilerOptionsForInferredProjectsArgs): void; + executeWithoutWaitingForResponse(command: 'reloadProjects', args: null): void; executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise; } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index adc73a29e3b98358c6ea4a254233fa0703d7d8ec..2d20a3c0a6404c7e86b6fb1a969c583c32d9503b 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -521,7 +521,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType const configureOptions: Proto.ConfigureRequestArguments = { hostInfo: 'vscode' }; - this.execute('configure', configureOptions); + this.executeWithoutWaitingForResponse('configure', configureOptions); this.setCompilerOptionsForInferredProjects(this._configuration); if (resendModels) { this._onResendModelsRequested.fire(); @@ -536,7 +536,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType const args: Proto.SetCompilerOptionsForInferredProjectsArgs = { options: this.getCompilerOptionsForInferredProjects(configuration) }; - this.execute('compilerOptionsForInferredProjects', args, true); + this.executeWithoutWaitingForResponse('compilerOptionsForInferredProjects', args); } private getCompilerOptionsForInferredProjects(configuration: TypeScriptServiceConfiguration): Proto.ExternalProjectCompilerOptions { @@ -679,19 +679,28 @@ export default class TypeScriptServiceClient extends Disposable implements IType return undefined; } - public executeAsync(command: string, args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise { - return this.executeImpl(command, args, { isAsync: true, token, expectsResult: true }); + public execute(command: string, args: any, token: vscode.CancellationToken): Promise { + return this.executeImpl(command, args, { + isAsync: false, + token, + expectsResult: true + }); } - public execute(command: string, args: any, expectsResultOrToken?: boolean | vscode.CancellationToken): Promise { - let token: vscode.CancellationToken | undefined = undefined; - let expectsResult = true; - if (typeof expectsResultOrToken === 'boolean') { - expectsResult = expectsResultOrToken; - } else { - token = expectsResultOrToken; - } - return this.executeImpl(command, args, { isAsync: false, token, expectsResult }); + public executeWithoutWaitingForResponse(command: string, args: any): void { + this.executeImpl(command, args, { + isAsync: false, + token: undefined, + expectsResult: false + }); + } + + public executeAsync(command: string, args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise { + return this.executeImpl(command, args, { + isAsync: true, + token, + expectsResult: true + }); } private executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean }): Promise { diff --git a/extensions/typescript-language-features/src/utils/cancellation.ts b/extensions/typescript-language-features/src/utils/cancellation.ts new file mode 100644 index 0000000000000000000000000000000000000000..10933baa9393dc421079db62e940de827ef9f8fc --- /dev/null +++ b/extensions/typescript-language-features/src/utils/cancellation.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; + +const nulTokenSource = new vscode.CancellationTokenSource(); + +export const nulToken = nulTokenSource.token; \ No newline at end of file diff --git a/extensions/typescript-language-features/src/utils/codeAction.ts b/extensions/typescript-language-features/src/utils/codeAction.ts index 6109ed70051437f83aa2c2317bfc9674d040d631..c45379e611ae44413f4b02fb425ad01403e63534 100644 --- a/extensions/typescript-language-features/src/utils/codeAction.ts +++ b/extensions/typescript-language-features/src/utils/codeAction.ts @@ -19,7 +19,8 @@ export function getEditForCodeAction( export async function applyCodeAction( client: ITypeScriptServiceClient, - action: Proto.CodeAction + action: Proto.CodeAction, + token: vscode.CancellationToken ): Promise { const workspaceEdit = getEditForCodeAction(client, action); if (workspaceEdit) { @@ -27,16 +28,17 @@ export async function applyCodeAction( return false; } } - return applyCodeActionCommands(client, action.commands); + return applyCodeActionCommands(client, action.commands, token); } export async function applyCodeActionCommands( client: ITypeScriptServiceClient, - commands: ReadonlyArray<{}> | undefined + commands: ReadonlyArray<{}> | undefined, + token: vscode.CancellationToken, ): Promise { if (commands && commands.length) { for (const command of commands) { - await client.execute('applyCodeActionCommand', { command }); + await client.execute('applyCodeActionCommand', { command }, token); } } return true;