Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/inlineEdits/vscode-node/features/diagnosticsBasedCompletions/asyncDiagnosticsCompletionProvider.ts
13406 views
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 { CodeActionData } from '../../../../../platform/inlineEdits/common/dataTypes/codeActionData';
7
import { LanguageId } from '../../../../../platform/inlineEdits/common/dataTypes/languageId';
8
import { ILogger } from '../../../../../platform/log/common/logService';
9
import { CancellationToken } from '../../../../../util/vs/base/common/cancellation';
10
import { TextReplacement } from '../../../../../util/vs/editor/common/core/edits/textEdit';
11
import { Position } from '../../../../../util/vs/editor/common/core/position';
12
import { IVSCodeObservableDocument } from '../../parts/vscodeWorkspace';
13
import { Diagnostic, DiagnosticCompletionItem, DiagnosticInlineEditRequestLogContext, IDiagnosticCodeAction, IDiagnosticCompletionProvider, isDiagnosticWithinDistance, log } from './diagnosticsCompletions';
14
15
class AsyncDiagnosticCompletionItem extends DiagnosticCompletionItem {
16
public static readonly type = 'async';
17
18
public readonly providerName = 'async';
19
20
constructor(
21
diagnostic: Diagnostic,
22
edit: TextReplacement,
23
workspaceDocument: IVSCodeObservableDocument,
24
) {
25
super(AsyncDiagnosticCompletionItem.type, diagnostic, edit, workspaceDocument);
26
}
27
}
28
export class AsyncDiagnosticCompletionProvider implements IDiagnosticCompletionProvider<AsyncDiagnosticCompletionItem> {
29
30
public static SupportedLanguages = new Set<string>(['typescript', 'javascript', 'typescriptreact', 'javascriptreact']);
31
32
public readonly providerName = 'async';
33
34
constructor(private readonly _logger: ILogger) { }
35
36
public providesCompletionsForDiagnostic(workspaceDocument: IVSCodeObservableDocument, diagnostic: Diagnostic, language: LanguageId, pos: Position): boolean {
37
if (!AsyncDiagnosticCompletionProvider.SupportedLanguages.has(language)) {
38
return false;
39
}
40
41
if (!isDiagnosticWithinDistance(workspaceDocument, diagnostic, pos, 3)) {
42
return false;
43
}
44
45
return isAsyncDiagnostics(diagnostic);
46
}
47
48
async provideDiagnosticCompletionItem(workspaceDocument: IVSCodeObservableDocument, sortedDiagnostics: Diagnostic[], pos: Position, logContext: DiagnosticInlineEditRequestLogContext, token: CancellationToken): Promise<AsyncDiagnosticCompletionItem | null> {
49
const missingAsyncDiagnostic = sortedDiagnostics.find(diagnostic => this.providesCompletionsForDiagnostic(workspaceDocument, diagnostic, workspaceDocument.languageId.get(), pos));
50
if (missingAsyncDiagnostic === undefined) {
51
return null;
52
}
53
54
// fetch code actions for missing async
55
const availableCodeActions = await workspaceDocument.getCodeActions(missingAsyncDiagnostic.range, 3, token);
56
if (availableCodeActions === undefined) {
57
log(`Fetching code actions likely timed out for \`${missingAsyncDiagnostic.message}\``, logContext, this._logger);
58
return null;
59
}
60
61
const asyncCodeActions = getAsyncCodeActions(availableCodeActions, workspaceDocument);
62
if (asyncCodeActions.length === 0) {
63
log('No async code actions found in the available code actions', logContext, this._logger);
64
return null;
65
}
66
67
const asyncCodeActionToShow = asyncCodeActions[0];
68
const item = new AsyncDiagnosticCompletionItem(missingAsyncDiagnostic, asyncCodeActionToShow.edit, workspaceDocument);
69
70
log(`Created async completion item for: \`${missingAsyncDiagnostic.toString()}\``, logContext, this._logger);
71
72
return item;
73
}
74
}
75
76
function isAsyncDiagnostics(diagnostic: Diagnostic): boolean {
77
return diagnostic.data.code === 1308;
78
}
79
80
const CODE_ACTION_ASYNC_TITLE_PREFIXES = ['Add async', 'Update async'];
81
82
function getAsyncCodeActions(codeActions: CodeActionData[], workspaceDocument: IVSCodeObservableDocument): IDiagnosticCodeAction[] {
83
84
const asyncCodeActions: IDiagnosticCodeAction[] = [];
85
for (const codeAction of codeActions) {
86
const asyncTitlePrefix = CODE_ACTION_ASYNC_TITLE_PREFIXES.find(prefix => codeAction.title.startsWith(prefix));
87
88
const isAsyncCodeAction = !!asyncTitlePrefix;
89
if (!isAsyncCodeAction) {
90
continue;
91
}
92
93
if (!codeAction.edits) {
94
continue;
95
}
96
97
const joinedEdit = TextReplacement.joinReplacements(codeAction.edits, workspaceDocument.value.get());
98
99
asyncCodeActions.push({
100
...codeAction,
101
edit: joinedEdit,
102
});
103
}
104
105
return asyncCodeActions;
106
}
107
108