Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/conversation/vscode-node/logWorkspaceState.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
7
import * as vscode from 'vscode';
8
import { IDebugOutputService } from '../../../platform/debug/common/debugOutputService';
9
import { IGitService } from '../../../platform/git/common/gitService';
10
import { ILanguageDiagnosticsService } from '../../../platform/languages/common/languageDiagnosticsService';
11
import { ILanguageFeaturesService } from '../../../platform/languages/common/languageFeaturesService';
12
import { ITabsAndEditorsService } from '../../../platform/tabs/common/tabsAndEditorsService';
13
import { ITerminalService } from '../../../platform/terminal/common/terminalService';
14
import { IWorkspaceService } from '../../../platform/workspace/common/workspaceService';
15
import { ISerializedDiagnosticRelatedInformation, ISerializedWorkspaceState } from '../../../platform/workspaceState/common/promptContextModel';
16
import { coalesce } from '../../../util/vs/base/common/arrays';
17
import { Disposable } from '../../../util/vs/base/common/lifecycle';
18
import { relativePath } from '../../../util/vs/base/common/resources';
19
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
20
import { IExtensionContribution } from '../../common/contributions';
21
22
export class LogWorkspaceStateContribution extends Disposable implements IExtensionContribution {
23
constructor(
24
@IInstantiationService instantiationService: IInstantiationService,
25
) {
26
super();
27
28
// register command "Developer: Log Workbench State"
29
this._register(vscode.commands.registerCommand('github.copilot.debug.workbenchState', async () => {
30
const symbolQueries = await vscode.window.showInputBox({
31
prompt: 'Enter a comma-separated list of symbol queries. Can be left blank if not using WorkspaceSymbols',
32
});
33
// Show a quick input asking the user for a file name
34
const fileName = await vscode.window.showInputBox({
35
prompt: 'Enter a file name - .state.json will be appended as the extension',
36
value: 'workspaceState',
37
});
38
if (!fileName) {
39
return;
40
}
41
const state = await instantiationService.createInstance(WorkspaceStateSnapshotHelper).captureWorkspaceStateSnapshot(symbolQueries?.split(',') ?? []);
42
// Get workspace root
43
const workspaceRoot = vscode.workspace.workspaceFolders?.[0].uri;
44
if (!workspaceRoot) {
45
return;
46
}
47
// Write the file
48
const fileUri = vscode.Uri.joinPath(workspaceRoot, `${fileName}.state.json`);
49
let serializedState = JSON.stringify(state, null, 2);
50
// Replace workspaceRoot with `./` to make the file path relative
51
serializedState = serializedState.replace(new RegExp(`${workspaceRoot.fsPath}/`, 'g'), './');
52
vscode.workspace.fs.writeFile(fileUri, Buffer.from(serializedState));
53
}));
54
}
55
}
56
57
export class WorkspaceStateSnapshotHelper {
58
/**
59
* Constructs a new instance of the PromptContextModel.
60
*
61
* @param tabAndEditorsService - Service for managing tabs and editors.
62
* @param languageDiagnosticService - Service for providing language diagnostics.
63
* @param languageService - Service for language features.
64
* @param workspaceService - Service for workspace management.
65
* @param terminalService - Service for terminal operations.
66
* @param debugOutputService - Service for debug output.
67
* @param gitService - Service for Git operations.
68
*/
69
constructor(
70
@ITabsAndEditorsService private readonly tabAndEditorsService: ITabsAndEditorsService,
71
@ILanguageDiagnosticsService private readonly languageDiagnosticService: ILanguageDiagnosticsService,
72
@ILanguageFeaturesService private readonly languageService: ILanguageFeaturesService,
73
@IWorkspaceService private readonly workspaceService: IWorkspaceService,
74
@ITerminalService private readonly terminalService: ITerminalService,
75
@IDebugOutputService private readonly debugOutputService: IDebugOutputService,
76
@IGitService private readonly gitService: IGitService
77
) { }
78
79
public async captureWorkspaceStateSnapshot(symbolQueries: string[]): Promise<ISerializedWorkspaceState> {
80
const workspaceFoldersFilePaths = this.workspaceService.getWorkspaceFolders().map(w => w.fsPath + '/');
81
const notebookDocumentFilePaths = this.workspaceService.notebookDocuments.map(d => d.uri.fsPath);
82
const symbols = (await Promise.all(symbolQueries.map(q => this.languageService.getWorkspaceSymbols(q)))).flat();
83
const serializedSymbols = symbols.map(s => ({
84
name: s.name,
85
kind: s.kind,
86
containerName: s.containerName,
87
filePath: s.location.uri.fsPath,
88
start: s.location.range.start,
89
end: s.location.range.end,
90
}));
91
const activeFileDiagnostics = !this.tabAndEditorsService.activeTextEditor ? [] : this.languageDiagnosticService.getDiagnostics(this.tabAndEditorsService.activeTextEditor.document.uri).map(d => ({
92
start: d.range.start,
93
end: d.range.end,
94
message: d.message,
95
severity: d.severity,
96
relatedInformation: d.relatedInformation?.map(serializeRelatedInformation)
97
}));
98
const activeTextEditor = this.tabAndEditorsService.activeTextEditor ? {
99
selections: this.tabAndEditorsService.activeTextEditor?.selections.map(s => ({
100
anchor: s.anchor,
101
active: s.active,
102
isReversed: s.isReversed,
103
})) ?? [],
104
documentFilePath: this.tabAndEditorsService.activeTextEditor?.document.uri.fsPath ?? '',
105
visibleRanges: this.tabAndEditorsService.activeTextEditor?.visibleRanges.map(r => ({
106
start: r.start,
107
end: r.end
108
})) ?? [],
109
languageId: this.tabAndEditorsService.activeTextEditor?.document.languageId ?? 'javascript',
110
} : undefined;
111
const terminalLastCommand = this.terminalService.terminalLastCommand ? {
112
commandLine: this.terminalService.terminalLastCommand.commandLine,
113
cwd: typeof this.terminalService.terminalLastCommand.cwd === 'object' ? this.terminalService.terminalLastCommand.cwd.toString() : this.terminalService.terminalLastCommand.cwd,
114
exitCode: this.terminalService.terminalLastCommand.exitCode,
115
output: this.terminalService.terminalLastCommand.output,
116
} : undefined;
117
const workspaceState: ISerializedWorkspaceState = {
118
workspaceFoldersFilePaths,
119
workspaceFolderFilePath: undefined,
120
symbols: serializedSymbols,
121
activeFileDiagnostics,
122
activeTextEditor,
123
debugConsoleOutput: this.debugOutputService.consoleOutput,
124
terminalBuffer: this.terminalService.terminalBuffer,
125
terminalLastCommand,
126
terminalSelection: this.terminalService.terminalSelection,
127
terminalShellType: this.terminalService.terminalShellType,
128
repoContexts: this.gitService.repositories,
129
notebookDocumentFilePaths,
130
textDocumentFilePaths: coalesce(this.workspaceService.textDocuments.map(doc => {
131
const parentFolder = this.workspaceService.getWorkspaceFolder(doc.uri);
132
return parentFolder ? relativePath(parentFolder, doc.uri) : undefined;
133
})),
134
activeNotebookEditor: undefined
135
};
136
137
return workspaceState;
138
}
139
}
140
141
function serializeRelatedInformation(r: vscode.DiagnosticRelatedInformation): ISerializedDiagnosticRelatedInformation {
142
return {
143
filePath: r.location.uri.fsPath,
144
start: r.location.range.start,
145
end: r.location.range.end,
146
message: r.message
147
};
148
}
149
150