Path: blob/main/extensions/copilot/src/extension/inlineEdits/vscode-node/features/diagnosticsBasedCompletions/asyncDiagnosticsCompletionProvider.ts
13406 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { CodeActionData } from '../../../../../platform/inlineEdits/common/dataTypes/codeActionData';6import { LanguageId } from '../../../../../platform/inlineEdits/common/dataTypes/languageId';7import { ILogger } from '../../../../../platform/log/common/logService';8import { CancellationToken } from '../../../../../util/vs/base/common/cancellation';9import { TextReplacement } from '../../../../../util/vs/editor/common/core/edits/textEdit';10import { Position } from '../../../../../util/vs/editor/common/core/position';11import { IVSCodeObservableDocument } from '../../parts/vscodeWorkspace';12import { Diagnostic, DiagnosticCompletionItem, DiagnosticInlineEditRequestLogContext, IDiagnosticCodeAction, IDiagnosticCompletionProvider, isDiagnosticWithinDistance, log } from './diagnosticsCompletions';1314class AsyncDiagnosticCompletionItem extends DiagnosticCompletionItem {15public static readonly type = 'async';1617public readonly providerName = 'async';1819constructor(20diagnostic: Diagnostic,21edit: TextReplacement,22workspaceDocument: IVSCodeObservableDocument,23) {24super(AsyncDiagnosticCompletionItem.type, diagnostic, edit, workspaceDocument);25}26}27export class AsyncDiagnosticCompletionProvider implements IDiagnosticCompletionProvider<AsyncDiagnosticCompletionItem> {2829public static SupportedLanguages = new Set<string>(['typescript', 'javascript', 'typescriptreact', 'javascriptreact']);3031public readonly providerName = 'async';3233constructor(private readonly _logger: ILogger) { }3435public providesCompletionsForDiagnostic(workspaceDocument: IVSCodeObservableDocument, diagnostic: Diagnostic, language: LanguageId, pos: Position): boolean {36if (!AsyncDiagnosticCompletionProvider.SupportedLanguages.has(language)) {37return false;38}3940if (!isDiagnosticWithinDistance(workspaceDocument, diagnostic, pos, 3)) {41return false;42}4344return isAsyncDiagnostics(diagnostic);45}4647async provideDiagnosticCompletionItem(workspaceDocument: IVSCodeObservableDocument, sortedDiagnostics: Diagnostic[], pos: Position, logContext: DiagnosticInlineEditRequestLogContext, token: CancellationToken): Promise<AsyncDiagnosticCompletionItem | null> {48const missingAsyncDiagnostic = sortedDiagnostics.find(diagnostic => this.providesCompletionsForDiagnostic(workspaceDocument, diagnostic, workspaceDocument.languageId.get(), pos));49if (missingAsyncDiagnostic === undefined) {50return null;51}5253// fetch code actions for missing async54const availableCodeActions = await workspaceDocument.getCodeActions(missingAsyncDiagnostic.range, 3, token);55if (availableCodeActions === undefined) {56log(`Fetching code actions likely timed out for \`${missingAsyncDiagnostic.message}\``, logContext, this._logger);57return null;58}5960const asyncCodeActions = getAsyncCodeActions(availableCodeActions, workspaceDocument);61if (asyncCodeActions.length === 0) {62log('No async code actions found in the available code actions', logContext, this._logger);63return null;64}6566const asyncCodeActionToShow = asyncCodeActions[0];67const item = new AsyncDiagnosticCompletionItem(missingAsyncDiagnostic, asyncCodeActionToShow.edit, workspaceDocument);6869log(`Created async completion item for: \`${missingAsyncDiagnostic.toString()}\``, logContext, this._logger);7071return item;72}73}7475function isAsyncDiagnostics(diagnostic: Diagnostic): boolean {76return diagnostic.data.code === 1308;77}7879const CODE_ACTION_ASYNC_TITLE_PREFIXES = ['Add async', 'Update async'];8081function getAsyncCodeActions(codeActions: CodeActionData[], workspaceDocument: IVSCodeObservableDocument): IDiagnosticCodeAction[] {8283const asyncCodeActions: IDiagnosticCodeAction[] = [];84for (const codeAction of codeActions) {85const asyncTitlePrefix = CODE_ACTION_ASYNC_TITLE_PREFIXES.find(prefix => codeAction.title.startsWith(prefix));8687const isAsyncCodeAction = !!asyncTitlePrefix;88if (!isAsyncCodeAction) {89continue;90}9192if (!codeAction.edits) {93continue;94}9596const joinedEdit = TextReplacement.joinReplacements(codeAction.edits, workspaceDocument.value.get());9798asyncCodeActions.push({99...codeAction,100edit: joinedEdit,101});102}103104return asyncCodeActions;105}106107108