-
Notifications
You must be signed in to change notification settings - Fork 190
/
Copy pathextension.ts
144 lines (117 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
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
/*
* extension.ts (and activateMockDebug.ts) forms the "plugin" that plugs into VS Code and contains the code that
* connects VS Code with the debug adapter.
*
* extension.ts contains code for launching the debug adapter in three different ways:
* - as an external program communicating with VS Code via stdin/stdout,
* - as a server process communicating with VS Code via sockets or named pipes, or
* - as inlined code running in the extension itself (default).
*
* Since the code in extension.ts uses node.js APIs it cannot run in the browser.
*/
'use strict';
import * as Net from 'net';
import * as vscode from 'vscode';
import { randomBytes } from 'crypto';
import { tmpdir } from 'os';
import { join } from 'path';
import { platform } from 'process';
import { ProviderResult } from 'vscode';
import { MockDebugSession } from './mockDebug';
import { activateMockDebug, workspaceFileAccessor } from './activateMockDebug';
/*
* 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' | 'namedPipeServer' | 'inline' = 'inline';
export function activate(context: vscode.ExtensionContext) {
// debug adapters can be run in different ways by using a vscode.DebugAdapterDescriptorFactory:
switch (runMode) {
case 'server':
// run the debug adapter as a server inside the extension and communicate via a socket
activateMockDebug(context, new MockDebugAdapterServerDescriptorFactory());
break;
case 'namedPipeServer':
// run the debug adapter as a server inside the extension and communicate via a named pipe (Windows) or UNIX domain socket (non-Windows)
activateMockDebug(context, new MockDebugAdapterNamedPipeServerDescriptorFactory());
break;
case 'external': default:
// run the debug adapter as a separate process
activateMockDebug(context, new DebugAdapterExecutableFactory());
break;
case 'inline':
// run the debug adapter inside the extension and directly talk to it
activateMockDebug(context);
break;
}
}
export function deactivate() {
// nothing to do
}
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: { "envVariable": "some value" }
};
executable = new vscode.DebugAdapterExecutable(command, args, options);
}
// make VS Code launch the DA executable
return executable;
}
}
class MockDebugAdapterServerDescriptorFactory 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(workspaceFileAccessor);
session.setRunAsServer(true);
session.start(socket as NodeJS.ReadableStream, socket);
}).listen(0);
}
// make VS Code connect to debug server
return new vscode.DebugAdapterServer((this.server.address() as Net.AddressInfo).port);
}
dispose() {
if (this.server) {
this.server.close();
}
}
}
class MockDebugAdapterNamedPipeServerDescriptorFactory 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 named pipe path
const pipeName = randomBytes(10).toString('utf8');
const pipePath = platform === "win32" ? join('\\\\.\\pipe\\', pipeName) : join(tmpdir(), pipeName);
this.server = Net.createServer(socket => {
const session = new MockDebugSession(workspaceFileAccessor);
session.setRunAsServer(true);
session.start(<NodeJS.ReadableStream>socket, socket);
}).listen(pipePath);
}
// make VS Code connect to debug server
return new vscode.DebugAdapterNamedPipeServer(this.server.address() as string);
}
dispose() {
if (this.server) {
this.server.close();
}
}
}