-
Notifications
You must be signed in to change notification settings - Fork 195
/
Copy pathextension.ts
150 lines (120 loc) · 5.09 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
144
145
146
147
148
149
150
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import { WorkspaceFolder, DebugConfiguration, ProviderResult, CancellationToken } from 'vscode';
import { MockDebugSession } from './mockDebug';
import * as Net from 'net';
/*
* The compile time flag 'runMode' controls how the debug adapter is run.
* Please note: the test suite only supports 'external' mode.
*/
const runMode: 'external' | 'server' | 'inline' = 'external';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('extension.mock-debug.getProgramName', config => {
return vscode.window.showInputBox({
placeHolder: "Please enter the name of a markdown file in the workspace folder",
value: "readme.md"
});
}));
// register a configuration provider for 'mock' debug type
const provider = new MockConfigurationProvider();
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('mock', provider));
// debug adapters can be run in different ways by using a vscode.DebugAdapterDescriptorFactory:
let factory: vscode.DebugAdapterDescriptorFactory;
switch (runMode) {
case 'server':
// run the debug adapter as a server inside the extension and communicating via a socket
factory = new MockDebugAdapterDescriptorFactory();
break;
case 'inline':
// run the debug adapter inside the extension and directly talk to it
factory = new InlineDebugAdapterFactory();
break;
case 'external': default:
// run the debug adapter as a separate process
factory = new DebugAdapterExecutableFactory();
break;
}
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('mock', factory));
if ('dispose' in factory) {
context.subscriptions.push(factory);
}
}
export function deactivate() {
// nothing to do
}
class MockConfigurationProvider implements vscode.DebugConfigurationProvider {
/**
* Massage a debug configuration just before a debug session is being launched,
* e.g. add all missing attributes to the debug configuration.
*/
resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration> {
// if launch.json is missing or empty
if (!config.type && !config.request && !config.name) {
const editor = vscode.window.activeTextEditor;
if (editor && editor.document.languageId === 'markdown') {
config.type = 'mock';
config.name = 'Launch';
config.request = 'launch';
config.program = '${file}';
config.stopOnEntry = true;
}
}
if (!config.program) {
return vscode.window.showInformationMessage("Cannot find a program to debug").then(_ => {
return undefined; // abort launch
});
}
return config;
}
}
class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescriptorFactory {
// The following use of a DebugAdapter factory shows how to control what debug adapter executable is used.
// Since the code implements the default behavior, it is absolutely not neccessary and we show it here only for educational purpose.
createDebugAdapterDescriptor(_session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): ProviderResult<vscode.DebugAdapterDescriptor> {
// param "executable" contains the executable optionally specified in the package.json (if any)
// use the executable specified in the package.json if it exists or determine it based on some other information (e.g. the session)
if (!executable) {
const command = "absolute path to my DA executable";
const args = [
"some args",
"another arg"
];
const options = {
cwd: "working directory for executable",
env: { "VAR": "some value" }
};
executable = new vscode.DebugAdapterExecutable(command, args, options);
}
// make VS Code launch the DA executable
return executable;
}
}
class MockDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
private server?: Net.Server;
createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
if (!this.server) {
// start listening on a random port
this.server = Net.createServer(socket => {
const session = new MockDebugSession();
session.setRunAsServer(true);
session.start(<NodeJS.ReadableStream>socket, socket);
}).listen(0);
}
// make VS Code connect to debug server
return new vscode.DebugAdapterServer((<Net.AddressInfo>this.server.address()).port);
}
dispose() {
if (this.server) {
this.server.close();
}
}
}
class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory {
createDebugAdapterDescriptor(_session: vscode.DebugSession): ProviderResult<vscode.DebugAdapterDescriptor> {
// since DebugAdapterInlineImplementation is proposed API, a cast to <any> is required for now
return <any>new vscode.DebugAdapterInlineImplementation(new MockDebugSession());
}
}