diff --git a/coreclr-debug/.gitignore b/coreclr-debug/.gitignore index 0541f8ebe1..ce4b985431 100644 --- a/coreclr-debug/.gitignore +++ b/coreclr-debug/.gitignore @@ -2,4 +2,5 @@ bin obj project.lock.json debugAdapters -install.log \ No newline at end of file +install.log +extension.log \ No newline at end of file diff --git a/package.json b/package.json index cdfefd071a..cb840c8ecb 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "github-releases": "^0.3.0", "run-in-terminal": "*", "semver": "*", + "vscode-debugprotocol": "^1.6.1", "vscode-extension-telemetry": "0.0.4", "tmp": "0.0.28", "open": "*" @@ -49,7 +50,7 @@ "onCommand:o.showOutput", "onCommand:o.execute-last-command", "onCommand:dotnet.restore", - "onCommand:csharp.addTasksJson", + "onCommand:csharp.downloadDebugger", "workspaceContains:project.json" ], "contributes": { @@ -105,6 +106,11 @@ "command": "dotnet.restore", "title": "Restore Packages", "category": "dotnet" + }, + { + "command": "csharp.downloadDebugger", + "title": "Download .NET Core Debugger", + "category": "Debug" } ], "keybindings": [ @@ -154,10 +160,9 @@ "csharp" ] }, - "program": "./coreclr-debug/debugAdapters/OpenDebugAD7", - "windows": { - "program": "./coreclr-debug/debugAdapters/OpenDebugAD7.exe" - }, + "runtime": "node", + "runtimeArgs": [], + "program": "./out/coreclr-debug/proxy.js", "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", "configurationAttributes": { "launch": { @@ -380,4 +385,4 @@ } ] } -} +} \ No newline at end of file diff --git a/src/coreclr-debug.ts b/src/coreclr-debug/main.ts similarity index 70% rename from src/coreclr-debug.ts rename to src/coreclr-debug/main.ts index df33d9b86a..0abcd6fd88 100644 --- a/src/coreclr-debug.ts +++ b/src/coreclr-debug/main.ts @@ -1,263 +1,264 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as vscode from 'vscode'; -import * as child_process from 'child_process'; -import * as fs from 'fs'; -import * as path from 'path'; -import TelemetryReporter from 'vscode-extension-telemetry'; - -let _coreClrDebugDir: string; -let _debugAdapterDir: string; -let _channel: vscode.OutputChannel; -let _installLog: NodeJS.WritableStream; -let _reporter: TelemetryReporter; // Telemetry reporter -const _completionFileName: string = 'install.complete'; - -export function installCoreClrDebug(context: vscode.ExtensionContext, reporter: TelemetryReporter) { - _coreClrDebugDir = path.join(context.extensionPath, 'coreclr-debug'); - _debugAdapterDir = path.join(_coreClrDebugDir, 'debugAdapters'); - - if (existsSync(path.join(_debugAdapterDir, _completionFileName))) { - console.log('.NET Core Debugger tools already installed'); - return; - } - - if (!isOnPath('dotnet')) { - const getDotNetMessage = "Get .NET CLI tools"; - vscode.window.showErrorMessage("The .NET CLI tools cannot be located. .NET Core debugging will not be enabled. Make sure .NET CLI tools are installed and are on the path.", - getDotNetMessage).then(function (value) { - if (value === getDotNetMessage) { - var open = require('open'); - open("http://dotnet.github.io/getting-started/"); - } - }); - - return; - } - - _reporter = reporter; - _channel = vscode.window.createOutputChannel('coreclr-debug'); - - // Create our log file and override _channel.append to also outpu to the log - _installLog = fs.createWriteStream(path.join(_coreClrDebugDir, 'install.log')); - (function() { - let proxied = _channel.append; - _channel.append = function(val: string) { - _installLog.write(val); - proxied.apply(this, arguments); - }; - })(); - - vscode.window.setStatusBarMessage("Downloading and configuring the .NET Core Debugger..."); - - let installStage = 'dotnet restore'; - let installError = ''; - - spawnChildProcess('dotnet', ['--verbose', 'restore', '--configfile', 'NuGet.config'], _channel, _coreClrDebugDir) - .then(function() { - installStage = "dotnet publish"; - return spawnChildProcess('dotnet', ['--verbose', 'publish', '-o', _debugAdapterDir], _channel, _coreClrDebugDir); - }).then(function() { - installStage = "ensureAd7"; - return ensureAd7EngineExists(_channel, _debugAdapterDir); - }).then(function() { - installStage = "additionalTasks"; - let promises: Promise[] = []; - - promises.push(renameDummyEntrypoint()); - promises.push(removeLibCoreClrTraceProvider()); - - return Promise.all(promises); - }).then(function() { - installStage = "writeCompletionFile"; - return writeCompletionFile(); - }).then(function() { - installStage = "completeSuccess"; - vscode.window.setStatusBarMessage('Successfully installed .NET Core Debugger.'); - }) - .catch(function(error) { - const viewLogMessage = "View Log"; - vscode.window.showErrorMessage('Error while installing .NET Core Debugger.', viewLogMessage).then(function (value) { - if (value === viewLogMessage) { - _channel.show(vscode.ViewColumn.Three); - } - }) - - installError = error.toString(); - console.log(error); - }).then(function() { - // log telemetry - logTelemetry('Acquisition', {installStage: installStage, installError: installError}); - }); -} - -function logTelemetry(eventName: string, properties?: {[prop: string]: string}) { - if (_reporter) - { - _reporter.sendTelemetryEvent('coreclr-debug/' + eventName, properties); - } -} - -function writeCompletionFile() : Promise { - return new Promise(function(resolve, reject) { - fs.writeFile(path.join(_debugAdapterDir, _completionFileName), '', function(err) { - if (err) { - reject(err.code); - } - else { - resolve(); - } - }); - }); -} - -function renameDummyEntrypoint() : Promise { - let src = path.join(_debugAdapterDir, 'dummy'); - let dest = path.join(_debugAdapterDir, 'OpenDebugAD7'); - - src += getPlatformExeExtension(); - dest += getPlatformExeExtension(); - - const promise = new Promise(function(resolve, reject) { - fs.rename(src, dest, function(err) { - if (err) { - reject(err.code); - } else { - resolve(); - } - }); - }); - - return promise; -} - -function removeLibCoreClrTraceProvider() : Promise -{ - const filePath = path.join(_debugAdapterDir, 'libcoreclrtraceptprovider' + getPlatformLibExtension()); - - if (!existsSync(filePath)) { - return Promise.resolve(); - } else { - return new Promise(function(resolve, reject) { - fs.unlink(filePath, function(err) { - if (err) { - reject(err.code); - } else { - _channel.appendLine('Succesfully deleted ' + filePath); - resolve(); - } - }); - }); - } -} - -function existsSync(path: string) : boolean { - try { - fs.accessSync(path, fs.F_OK); - return true; - } catch (err) { - if (err.code === 'ENOENT') { - return false; - } else { - throw Error(err.code); - } - } -} - -function getPlatformExeExtension() : string { - if (process.platform === 'win32') { - return '.exe'; - } - - return ''; -} - -function getPlatformLibExtension() : string { - switch (process.platform) { - case 'win32': - return '.dll'; - case 'darwin': - return '.dylib'; - case 'linux': - return '.so'; - default: - throw Error('Unsupported platform ' + process.platform); - } -} - -// Determines if the specified command is in one of the directories in the PATH environment variable. -function isOnPath(command : string) : boolean { - let pathValue = process.env['PATH']; - if (!pathValue) { - return false; - } - let fileName = command; - let seperatorChar = ':'; - if (process.platform == 'win32') { - // on Windows, add a '.exe', and the path is semi-colon seperatode - fileName = fileName + ".exe"; - seperatorChar = ';'; - } - - let pathSegments: string[] = pathValue.split(seperatorChar); - for (let segment of pathSegments) { - if (segment.length === 0 || !path.isAbsolute(segment)) { - continue; - } - - const segmentPath = path.join(segment, fileName); - if (existsSync(segmentPath)) { - return true; - } - } - - return false; -} - -function ensureAd7EngineExists(channel: vscode.OutputChannel, outputDirectory: string) : Promise { - let filePath = path.join(outputDirectory, "coreclr.ad7Engine.json"); - return new Promise((resolve, reject) => { - fs.exists(filePath, (exists) => { - if (exists) { - return resolve(); - } else { - channel.appendLine(`${filePath} does not exist.`); - channel.appendLine(''); - // NOTE: The minimum build number is actually less than 1584, but this is the minimum - // build that I have tested. - channel.appendLine("Error: The .NET CLI did not correctly restore debugger files. Ensure that you have .NET CLI version 1.0.0 build #001584 or newer. You can check your .NET CLI version using 'dotnet --version'."); - return reject("The .NET CLI did not correctly restore debugger files."); - } - }); - }); -} - -function spawnChildProcess(process: string, args: string[], channel: vscode.OutputChannel, workingDirectory: string) : Promise { - const promise = new Promise(function(resolve, reject) { - const child = child_process.spawn(process, args, {cwd: workingDirectory}); - - child.stdout.on('data', (data) => { - channel.append(`${data}`); - }); - - child.stderr.on('data', (data) => { - channel.appendLine(`Error: ${data}`); - }); - - child.on('close', (code: number) => { - if (code != 0) { - channel.appendLine(`${process} exited with error code ${code}`); - reject(new Error(code.toString())); - } - else { - resolve(); - } - }); - }); - - return promise; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as vscode from 'vscode'; +import * as child_process from 'child_process'; +import * as fs from 'fs'; +import * as path from 'path'; +import TelemetryReporter from 'vscode-extension-telemetry'; +import CoreClrDebugUtil from './util' + +let _channel: vscode.OutputChannel; +let _installLog: NodeJS.WritableStream; +let _reporter: TelemetryReporter; // Telemetry reporter +let _util: CoreClrDebugUtil; + +export function activate(context: vscode.ExtensionContext, reporter: TelemetryReporter) { + _util = new CoreClrDebugUtil(context.extensionPath); + + if (CoreClrDebugUtil.existsSync(_util.installCompleteFilePath())) { + console.log('.NET Core Debugger tools already installed'); + return; + } + + if (!isOnPath('dotnet')) { + const getDotNetMessage = "Get .NET CLI tools"; + vscode.window.showErrorMessage("The .NET CLI tools cannot be located. .NET Core debugging will not be enabled. Make sure .NET CLI tools are installed and are on the path.", + getDotNetMessage).then(function (value) { + if (value === getDotNetMessage) { + let open = require('open'); + open("http://dotnet.github.io/getting-started/"); + } + }); + + return; + } + + _reporter = reporter; + _channel = vscode.window.createOutputChannel('coreclr-debug'); + + // Create our log file and override _channel.append to also output to the log + _installLog = fs.createWriteStream(_util.installLogPath()); + (function() { + let proxied = _channel.append; + _channel.append = function(val: string) { + _installLog.write(val); + proxied.apply(this, arguments); + }; + })(); + + let statusBarMessage = vscode.window.setStatusBarMessage("Downloading and configuring the .NET Core Debugger..."); + + let installStage = 'installBegin'; + let installError = ''; + + writeInstallBeginFile().then(function() { + installStage = 'dotnetRestore' + return spawnChildProcess('dotnet', ['--verbose', 'restore', '--configfile', 'NuGet.config'], _channel, _util.coreClrDebugDir()) + }).then(function() { + installStage = "dotnetPublish"; + return spawnChildProcess('dotnet', ['--verbose', 'publish', '-o', _util.debugAdapterDir()], _channel, _util.coreClrDebugDir()); + }).then(function() { + installStage = "ensureAd7"; + return ensureAd7EngineExists(_channel, _util.debugAdapterDir()); + }).then(function() { + installStage = "additionalTasks"; + let promises: Promise[] = []; + + promises.push(renameDummyEntrypoint()); + promises.push(removeLibCoreClrTraceProvider()); + + return Promise.all(promises); + }).then(function() { + installStage = "rewriteManifest"; + rewriteManifest(); + installStage = "writeCompletionFile"; + return writeCompletionFile(); + }).then(function() { + installStage = "completeSuccess"; + statusBarMessage.dispose(); + vscode.window.setStatusBarMessage('Successfully installed .NET Core Debugger.'); + }) + .catch(function(error) { + const viewLogMessage = "View Log"; + vscode.window.showErrorMessage('Error while installing .NET Core Debugger.', viewLogMessage).then(function (value) { + if (value === viewLogMessage) { + _channel.show(vscode.ViewColumn.Three); + } + }); + statusBarMessage.dispose(); + + installError = error.toString(); + console.log(error); + + + }).then(function() { + // log telemetry and delete install begin file + logTelemetry('Acquisition', {installStage: installStage, installError: installError}); + + try { + deleteInstallBeginFile(); + } catch (err) { + // if this throws there's really nothing we can do + } + }); +} + +function logTelemetry(eventName: string, properties?: {[prop: string]: string}) { + if (_reporter) + { + _reporter.sendTelemetryEvent('coreclr-debug/' + eventName, properties); + } +} + +function rewriteManifest() : void { + const manifestPath = path.join(_util.extensionDir(), 'package.json'); + let manifestString = fs.readFileSync(manifestPath, 'utf8'); + let manifestObject = JSON.parse(manifestString); + manifestObject.contributes.debuggers[0].runtime = ''; + manifestObject.contributes.debuggers[0].program = './coreclr-debug/debugAdapters/OpenDebugAD7' + CoreClrDebugUtil.getPlatformExeExtension(); + manifestString = JSON.stringify(manifestObject, null, 2); + fs.writeFileSync(manifestPath, manifestString); +} + +function writeInstallBeginFile() : Promise { + return writeEmptyFile(_util.installBeginFilePath()); +} + +function deleteInstallBeginFile() { + if (CoreClrDebugUtil.existsSync(_util.installBeginFilePath())) { + fs.unlinkSync(_util.installBeginFilePath()); + } +} + +function writeCompletionFile() : Promise { + return writeEmptyFile(_util.installCompleteFilePath()); +} + +function writeEmptyFile(path: string) : Promise { + return new Promise(function(resolve, reject) { + fs.writeFile(path, '', function(err) { + if (err) { + reject(err.code); + } else { + resolve(); + } + }); + }); +} + +function renameDummyEntrypoint() : Promise { + let src = path.join(_util.debugAdapterDir(), 'dummy'); + let dest = path.join(_util.debugAdapterDir(), 'OpenDebugAD7'); + + src += CoreClrDebugUtil.getPlatformExeExtension(); + dest += CoreClrDebugUtil.getPlatformExeExtension(); + + const promise = new Promise(function(resolve, reject) { + fs.rename(src, dest, function(err) { + if (err) { + reject(err.code); + } else { + resolve(); + } + }); + }); + + return promise; +} + +function removeLibCoreClrTraceProvider() : Promise +{ + const filePath = path.join(_util.debugAdapterDir(), 'libcoreclrtraceptprovider' + CoreClrDebugUtil.getPlatformLibExtension()); + + if (!CoreClrDebugUtil.existsSync(filePath)) { + return Promise.resolve(); + } else { + return new Promise(function(resolve, reject) { + fs.unlink(filePath, function(err) { + if (err) { + reject(err.code); + } else { + _channel.appendLine('Succesfully deleted ' + filePath); + resolve(); + } + }); + }); + } +} + +// Determines if the specified command is in one of the directories in the PATH environment variable. +function isOnPath(command : string) : boolean { + let pathValue = process.env['PATH']; + if (!pathValue) { + return false; + } + let fileName = command; + let seperatorChar = ':'; + if (process.platform == 'win32') { + // on Windows, add a '.exe', and the path is semi-colon seperatode + fileName = fileName + ".exe"; + seperatorChar = ';'; + } + + let pathSegments: string[] = pathValue.split(seperatorChar); + for (let segment of pathSegments) { + if (segment.length === 0 || !path.isAbsolute(segment)) { + continue; + } + + const segmentPath = path.join(segment, fileName); + if (CoreClrDebugUtil.existsSync(segmentPath)) { + return true; + } + } + + return false; +} + +function ensureAd7EngineExists(channel: vscode.OutputChannel, outputDirectory: string) : Promise { + let filePath = path.join(outputDirectory, "coreclr.ad7Engine.json"); + return new Promise((resolve, reject) => { + fs.exists(filePath, (exists) => { + if (exists) { + return resolve(); + } else { + channel.appendLine(`${filePath} does not exist.`); + channel.appendLine(''); + // NOTE: The minimum build number is actually less than 1584, but this is the minimum + // build that I have tested. + channel.appendLine("Error: The .NET CLI did not correctly restore debugger files. Ensure that you have .NET CLI version 1.0.0 build #001584 or newer. You can check your .NET CLI version using 'dotnet --version'."); + return reject("The .NET CLI did not correctly restore debugger files."); + } + }); + }); +} + +function spawnChildProcess(process: string, args: string[], channel: vscode.OutputChannel, workingDirectory: string) : Promise { + const promise = new Promise(function(resolve, reject) { + const child = child_process.spawn(process, args, {cwd: workingDirectory}); + + child.stdout.on('data', (data) => { + channel.append(`${data}`); + }); + + child.stderr.on('data', (data) => { + channel.appendLine(`Error: ${data}`); + }); + + child.on('close', (code: number) => { + if (code != 0) { + channel.appendLine(`${process} exited with error code ${code}`); + reject(new Error(code.toString())); + } + else { + resolve(); + } + }); + }); + + return promise; } \ No newline at end of file diff --git a/src/coreclr-debug/proxy.ts b/src/coreclr-debug/proxy.ts new file mode 100644 index 0000000000..d6a9c3bfd4 --- /dev/null +++ b/src/coreclr-debug/proxy.ts @@ -0,0 +1,109 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as path from 'path'; +import { DebugProtocol } from 'vscode-debugprotocol'; +import * as child_process from 'child_process'; +import CoreClrDebugUtil from './util'; + +class ProxyErrorResponse implements DebugProtocol.ErrorResponse { + public body: { error?: DebugProtocol.Message }; + public request_seq: number; + public success: boolean; + public command: string; + public seq: number; + public type: string; + + constructor(public message: string) { + this.request_seq = 1; + this.seq = 1; + this.type = "response"; + this.success = false; + this.command = "initialize"; + } +} + +function serializeProtocolEvent(message: DebugProtocol.ProtocolMessage): string { + const payload: string = JSON.stringify(message); + const finalPayload: string = `Content-Length: ${payload.length}\r\n\r\n${payload}`; + return finalPayload; +} + +// The default extension manifest calls this proxy as the debugger program +// When installation of the debugger components finishes, the extension manifest is rewritten so that this proxy is no longer called +// If the debugger components have not finished downloading, the proxy displays an error message to the user +// If the debugger components have finished downloading, the manifest has been rewritten but has not been reloaded. +// This proxy will still be called and launch OpenDebugAD7 as a child process. +// During subsequent code sessions, the rewritten manifest will be loaded and this proxy will no longer be called. +function proxy() { + let util = new CoreClrDebugUtil(path.resolve(__dirname, '../../')); + + if (!CoreClrDebugUtil.existsSync(util.installCompleteFilePath())) { + if (CoreClrDebugUtil.existsSync(util.installBeginFilePath())) { + process.stdout.write(serializeProtocolEvent(new ProxyErrorResponse('The .NET Core Debugger is still being downloaded. See the Status Bar for more information.'))); + } else { + process.stdout.write(serializeProtocolEvent(new ProxyErrorResponse('Run \'Debug: Download .NET Core Debugger\' in the Command Palette or open a .NET project directory to download the .NET Core Debugger'))); + } + } + else + { + new Promise(function(resolve, reject) { + let processPath = path.join(util.debugAdapterDir(), "OpenDebugAD7" + CoreClrDebugUtil.getPlatformExeExtension()); + let args = process.argv.slice(2); + + // do not explicitly set a current working dir + // this seems to match what code does when OpenDebugAD7 is launched directly from the manifest + const child = child_process.spawn(processPath, args); + + // If we don't exit cleanly from the child process, log the error. + child.on('close', function(code: number) { + if (code !== 0) { + reject(new Error(code.toString())); + } else { + resolve(); + } + }); + + process.stdin.setEncoding('utf8'); + + child.on('error', function(data) { + util.logToFile(`Child error: ${data}`); + }); + + process.on('SIGTERM', function() { + child.kill(); + process.exit(0); + }); + + process.on('SIGHUP', function() { + child.kill(); + process.exit(0); + }); + + process.stdin.on('error', function(error) { + util.logToFile(`process.stdin error: ${error}`); + }); + + process.stdout.on('error', function(error) { + util.logToFile(`process.stdout error: ${error}`); + }); + + child.stdout.on('data', function(data) { + process.stdout.write(data); + }); + + process.stdin.on('data', function(data) { + child.stdin.write(data); + }); + + process.stdin.resume(); + }).catch(function(err) { + util.logToFile(`Promise failed: ${err}`); + }); + } +} + +proxy(); \ No newline at end of file diff --git a/src/coreclr-debug/util.ts b/src/coreclr-debug/util.ts new file mode 100644 index 0000000000..bae844c07f --- /dev/null +++ b/src/coreclr-debug/util.ts @@ -0,0 +1,120 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as path from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; + +let _extensionDir: string = ''; +let _coreClrDebugDir: string = ''; +let _debugAdapterDir: string = ''; +let _installLogPath: string = ''; +let _installBeginFilePath: string = ''; +let _installCompleteFilePath: string = ''; + +export default class CoreClrDebugUtil +{ + private _extensionDir: string = ''; + private _coreClrDebugDir: string = ''; + private _debugAdapterDir: string = ''; + private _installLogPath: string = ''; + private _installBeginFilePath: string = ''; + private _installCompleteFilePath: string = ''; + + constructor(extensionDir) { + _extensionDir = extensionDir; + _coreClrDebugDir = path.join(_extensionDir, 'coreclr-debug'); + _debugAdapterDir = path.join(_coreClrDebugDir, 'debugAdapters'); + _installLogPath = path.join(_coreClrDebugDir, 'install.log'); + _installBeginFilePath = path.join(_coreClrDebugDir, 'install.begin'); + _installCompleteFilePath = path.join(_debugAdapterDir, 'install.complete'); + } + + extensionDir(): string { + if (_extensionDir === '') + { + throw new Error('Failed to set extension directory'); + } + return _extensionDir; + } + + coreClrDebugDir(): string { + if (_coreClrDebugDir === '') { + throw new Error('Failed to set coreclrdebug directory'); + } + return _coreClrDebugDir; + } + + debugAdapterDir(): string { + if (_debugAdapterDir === '') { + throw new Error('Failed to set debugadpter directory'); + } + return _debugAdapterDir; + } + + installLogPath(): string { + if (_installLogPath === '') { + throw new Error('Failed to set install log path'); + } + return _installLogPath; + } + + installBeginFilePath(): string { + if (_installBeginFilePath === '') { + throw new Error('Failed to set install begin file path'); + } + return _installBeginFilePath; + } + + installCompleteFilePath(): string { + if (_installCompleteFilePath === '') + { + throw new Error('Failed to set install complete file path'); + } + return _installCompleteFilePath; + } + + static existsSync(path: string) : boolean { + try { + fs.accessSync(path, fs.F_OK); + return true; + } catch (err) { + if (err.code === 'ENOENT') { + return false; + } else { + throw Error(err.code); + } + } + } + + static getPlatformExeExtension() : string { + if (process.platform === 'win32') { + return '.exe'; + } + + return ''; + } + + static getPlatformLibExtension() : string { + switch (process.platform) { + case 'win32': + return '.dll'; + case 'darwin': + return '.dylib'; + case 'linux': + return '.so'; + default: + throw Error('Unsupported platform ' + process.platform); + } + } + + + /** Used for diagnostics only */ + logToFile(message: string): void { + let logFolder = path.resolve(this.coreClrDebugDir(), "extension.log"); + fs.writeFileSync(logFolder, `${message}${os.EOL}`, { flag: 'a' }); + } +} diff --git a/src/features/commands.ts b/src/features/commands.ts index d734afd16b..2cc72feb4b 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -23,8 +23,12 @@ export default function registerCommands(server: OmnisharpServer, extensionPath: let d5 = vscode.commands.registerCommand('o.execute-last-command', () => dnxExecuteLastCommand(server)); let d6 = vscode.commands.registerCommand('o.showOutput', () => server.getChannel().show(vscode.ViewColumn.Three)); let d7 = vscode.commands.registerCommand('dotnet.restore', () => dotnetRestore(server)); + + // register empty handler for csharp.installDebugger + // running the command activates the extension, which is all we need for installation to kickoff + let d8 = vscode.commands.registerCommand('csharp.downloadDebugger', () => { }); - return vscode.Disposable.from(d1, d2, d3, d4, d5, d6, d7); + return vscode.Disposable.from(d1, d2, d3, d4, d5, d6, d7, d8); } function pickProjectAndStart(server: OmnisharpServer) { diff --git a/src/omnisharpMain.ts b/src/omnisharpMain.ts index d31e1d08ca..ec5e51e04b 100644 --- a/src/omnisharpMain.ts +++ b/src/omnisharpMain.ts @@ -22,7 +22,7 @@ import registerCommands from './features/commands'; import {StdioOmnisharpServer} from './omnisharpServer'; import forwardChanges from './features/changeForwarding'; import reportStatus from './features/omnisharpStatus'; -import {installCoreClrDebug} from './coreclr-debug'; +import * as coreclrdebug from './coreclr-debug/main'; import {addAssetsIfNecessary} from './assets'; import * as vscode from 'vscode'; import TelemetryReporter from 'vscode-extension-telemetry'; @@ -90,9 +90,9 @@ export function activate(context: vscode.ExtensionContext): any { server.reportAndClearTelemetry(); server.stop(); })); - + // install coreclr-debug - installCoreClrDebug(context, reporter); + coreclrdebug.activate(context, reporter); context.subscriptions.push(...disposables); }