Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/intents/vscode-node/fixTestFailureContributions.ts
13399 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 * as l10n from '@vscode/l10n';
7
import * as vscode from 'vscode';
8
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
9
import { ITelemetryService } from '../../../platform/telemetry/common/telemetry';
10
import { ITestFailure, ITestProvider } from '../../../platform/testing/common/testProvider';
11
import { mapFindFirst } from '../../../util/vs/base/common/arraysFind';
12
import { Disposable, DisposableStore } from '../../../util/vs/base/common/lifecycle';
13
import { Intent } from '../../common/constants';
14
import { IExtensionContribution } from '../../common/contributions';
15
16
17
export class FixTestFailureContribution extends Disposable implements IExtensionContribution {
18
constructor(
19
@ITestProvider testProvider: ITestProvider,
20
@ITelemetryService telemetryService: ITelemetryService,
21
@IConfigurationService configurationService: IConfigurationService,
22
) {
23
super();
24
const store = this._register(new DisposableStore());
25
registerTestMessageSparkles(store, telemetryService, testProvider);
26
registerTestFailureCodeAction(testProvider, configurationService, store);
27
}
28
}
29
30
type FixCommandArgs = { message: vscode.TestMessage; test: vscode.TestItem | vscode.TestResultSnapshot; source?: 'sparkles' | 'testResultsPanel' | 'retry' };
31
32
function registerTestMessageSparkles(store: DisposableStore, telemetryService: ITelemetryService, testProvider: ITestProvider) {
33
function getLastFailureForItemOrChildren(item: vscode.TestItem): ITestFailure | undefined {
34
const failure = testProvider.getLastFailureFor(item);
35
return failure || mapFindFirst(item.children, ([, item]) => getLastFailureForItemOrChildren(item));
36
}
37
38
store.add(vscode.commands.registerCommand('github.copilot.tests.fixTestFailure.fromInline', (item: vscode.TestItem) => {
39
const failure = getLastFailureForItemOrChildren(item);
40
if (failure) {
41
openFixChat({
42
message: failure.task.messages[0],
43
test: failure.snapshot,
44
source: 'testResultsPanel',
45
});
46
}
47
}));
48
49
store.add(vscode.commands.registerCommand('github.copilot.tests.fixTestFailure', openFixChat));
50
51
async function openFixChat(args: FixCommandArgs) {
52
if (!args.test.uri) {
53
return; // should not happen based on context keys
54
}
55
56
/* __GDPR__
57
"intent.fixTestFailure.actioned" : {
58
"owner": "connor4312",
59
"comment": "Reports when we show a ",
60
"source": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Where the action was taken" }
61
}
62
*/
63
telemetryService.sendMSFTTelemetryEvent('intent.fixTestFailure.actioned', {
64
source: args.source ?? 'testResultsPanel',
65
});
66
67
const doc = await vscode.workspace.openTextDocument(args.test.uri);
68
await vscode.window.showTextDocument(doc, {
69
preserveFocus: false, // must transfer focus so editor chat starts at the right place
70
preview: true,
71
selection: args.test.range ? new vscode.Range(args.test.range.start, args.test.range.start) : undefined
72
});
73
74
await vscode.commands.executeCommand('vscode.editorChat.start', {
75
message: `/${Intent.Fix} the #testFailure`,
76
autoSend: true,
77
});
78
}
79
}
80
81
function registerTestFailureCodeAction(testProvider: ITestProvider, configurationService: IConfigurationService, store: DisposableStore) {
82
store.add(vscode.languages.registerCodeActionsProvider('*', {
83
provideCodeActions(document, range, context, token) {
84
const copilotCodeActionsEnabled = configurationService.getConfig(ConfigKey.EnableCodeActions);
85
if (!copilotCodeActionsEnabled) {
86
return;
87
}
88
89
const test = testProvider.getFailureAtPosition(document.uri, range.start);
90
if (!test) {
91
return undefined;
92
}
93
94
const ca = new vscode.CodeAction(l10n.t('Fix test failure'), vscode.CodeActionKind.QuickFix);
95
ca.isAI = true;
96
ca.command = {
97
title: l10n.t('Fix test failure'),
98
command: 'github.copilot.tests.fixTestFailure',
99
arguments: [{
100
message: test.task.messages[0],
101
test: test.snapshot,
102
source: 'sparkles',
103
} satisfies FixCommandArgs]
104
};
105
return [ca];
106
},
107
}));
108
}
109
110
111