Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
148 lines (118 sloc) 5.03 KB
/*---------------------------------------------------------
* 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 : any;
switch (runMode) {
case 'external':
// how to run the debug adapter as a separate process
factory = new DebugAdapterExecutableFactory();
break;
case 'server':
// how to run the debug adapter as a server inside the extension and communicating via a socket
factory = new MockDebugAdapterDescriptorFactory();
break;
case 'inline':
// how to run the debug adapter inside the extension
factory = new InlineDebugAdapterFactory();
break;
}
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('mock', 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(<any> new MockDebugSession());
}
}
You can’t perform that action at this time.