-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
extension.ts
143 lines (123 loc) · 8.08 KB
/
extension.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import * as os from 'os';
import { AttachPicker, RemoteAttachPicker, AttachItemsProvider } from './attachToProcess';
import { NativeAttachItemsProviderFactory } from './nativeAttach';
import { QuickPickConfigurationProvider, ConfigurationAssetProviderFactory, CppVsDbgConfigurationProvider, CppDbgConfigurationProvider, ConfigurationSnippetProvider, IConfigurationAssetProvider } from './configurationProvider';
import { CppdbgDebugAdapterDescriptorFactory, CppvsdbgDebugAdapterDescriptorFactory } from './debugAdapterDescriptorFactory';
import * as util from '../common';
import * as Telemetry from '../telemetry';
import * as nls from 'vscode-nls';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
// The extension deactivate method is asynchronous, so we handle the disposables ourselves instead of using extensonContext.subscriptions.
const disposables: vscode.Disposable[] = [];
export function buildAndDebugActiveFileStr(): string {
return ` - ${localize("build.and.debug.active.file", 'Build and debug active file')}`;
}
export function initialize(context: vscode.ExtensionContext): void {
// Activate Process Picker Commands
const attachItemsProvider: AttachItemsProvider = NativeAttachItemsProviderFactory.Get();
const attacher: AttachPicker = new AttachPicker(attachItemsProvider);
disposables.push(vscode.commands.registerCommand('extension.pickNativeProcess', () => attacher.ShowAttachEntries()));
const remoteAttacher: RemoteAttachPicker = new RemoteAttachPicker();
disposables.push(vscode.commands.registerCommand('extension.pickRemoteNativeProcess', (any) => remoteAttacher.ShowAttachEntries(any)));
// Activate ConfigurationProvider
const configurationProvider: IConfigurationAssetProvider = ConfigurationAssetProviderFactory.getConfigurationProvider();
// On non-windows platforms, the cppvsdbg debugger will not be registered for initial configurations.
// This will cause it to not show up on the dropdown list.
let vsdbgProvider: CppVsDbgConfigurationProvider | null = null;
if (os.platform() === 'win32') {
vsdbgProvider = new CppVsDbgConfigurationProvider(configurationProvider);
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppvsdbg', new QuickPickConfigurationProvider(vsdbgProvider)));
}
const provider: CppDbgConfigurationProvider = new CppDbgConfigurationProvider(configurationProvider);
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppdbg', new QuickPickConfigurationProvider(provider)));
disposables.push(vscode.commands.registerTextEditorCommand("C_Cpp.BuildAndDebugActiveFile", async (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => {
const folder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(textEditor.document.uri);
if (!folder) {
// Not enabled because we do not react to single-file mode correctly yet.
// We get an ENOENT when the user's c_cpp_properties.json is attempted to be parsed.
// The DefaultClient will also have its configuration accessed, but since it doesn't exist it errors out.
vscode.window.showErrorMessage('This command is not yet available for single-file mode.');
return Promise.resolve();
}
if (!util.fileIsCOrCppSource(textEditor.document.uri.fsPath)) {
vscode.window.showErrorMessage(localize("cannot.build.non.cpp", 'Cannot build and debug because the active file is not a C or C++ source file.'));
return Promise.resolve();
}
const configs: vscode.DebugConfiguration[] = (await provider.provideDebugConfigurations(folder)).filter(config =>
config.name.indexOf(buildAndDebugActiveFileStr()) !== -1);
if (vsdbgProvider) {
const vsdbgConfigs: vscode.DebugConfiguration[] = (await vsdbgProvider.provideDebugConfigurations(folder)).filter(config =>
config.name.indexOf(buildAndDebugActiveFileStr()) !== -1);
if (vsdbgConfigs) {
configs.push(...vsdbgConfigs);
}
}
interface MenuItem extends vscode.QuickPickItem {
configuration: vscode.DebugConfiguration;
}
const items: MenuItem[] = configs.map<MenuItem>(config => ({label: config.name, configuration: config}));
vscode.window.showQuickPick(items, {placeHolder: (items.length === 0 ? localize("no.compiler.found", "No compiler found") : localize("select.compiler", "Select a compiler"))}).then(async selection => {
if (!selection) {
return; // User canceled it.
}
if (selection.label.startsWith("cl.exe")) {
if (!process.env.DevEnvDir || process.env.DevEnvDir.length === 0) {
vscode.window.showErrorMessage(localize("cl.exe.not.available", '{0} build and debug is only usable when VS Code is run from the Developer Command Prompt for VS.', "cl.exe"));
return;
}
}
if (selection.configuration.preLaunchTask) {
if (folder) {
try {
await util.ensureBuildTaskExists(selection.configuration.preLaunchTask);
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" });
} catch (e) {
if (e && e.message === util.failedToParseTasksJson) {
vscode.window.showErrorMessage(util.failedToParseTasksJson);
}
return Promise.resolve();
}
} else {
return Promise.resolve();
// TODO uncomment this when single file mode works correctly.
// const buildTasks: vscode.Task[] = await getBuildTasks(true);
// const task: vscode.Task = buildTasks.find(task => task.name === selection.configuration.preLaunchTask);
// await vscode.tasks.executeTask(task);
// delete selection.configuration.preLaunchTask;
}
}
// Attempt to use the user's (possibly) modified configuration before using the generated one.
try {
await vscode.debug.startDebugging(folder, selection.configuration.name);
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "true" });
} catch (e) {
try {
vscode.debug.startDebugging(folder, selection.configuration);
} catch (e) {
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" });
}
}
});
}));
configurationProvider.getConfigurationSnippets();
const launchJsonDocumentSelector: vscode.DocumentSelector = [{
scheme: 'file',
language: 'jsonc',
pattern: '**/launch.json'
}];
// ConfigurationSnippetProvider needs to be initiallized after configurationProvider calls getConfigurationSnippets.
disposables.push(vscode.languages.registerCompletionItemProvider(launchJsonDocumentSelector, new ConfigurationSnippetProvider(configurationProvider)));
// Register Debug Adapters
disposables.push(vscode.debug.registerDebugAdapterDescriptorFactory(CppvsdbgDebugAdapterDescriptorFactory.DEBUG_TYPE, new CppvsdbgDebugAdapterDescriptorFactory(context)));
disposables.push(vscode.debug.registerDebugAdapterDescriptorFactory(CppdbgDebugAdapterDescriptorFactory.DEBUG_TYPE, new CppdbgDebugAdapterDescriptorFactory(context)));
vscode.Disposable.from(...disposables);
}
export function dispose(): void {
disposables.forEach(d => d.dispose());
}