From 6db54aa3b08548ca83833d56e3dc6c05b89c6b13 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Mon, 22 Feb 2016 16:45:42 -0800 Subject: [PATCH 1/9] Incorproate coreclr-debug into omnisharp extension 1. Adds coreclr-debug.ts to implement coreclr-debug acquisition and hooks it into omnisharp's activation handler 2. Adds the coreclr-debug directory containing the project.json, NuGet.config and dummy.cs required dotnet restore/publish 3. Adds the debugger section to contributes in package.json 4. Adds .vscodeignore to exclude items not needed at runtime from being packaged TODO: 1. Update project.json references 2. Update NuGet.config to not point to http://dbgnuget (switch to nuget.org once pacakges are published publicly) 3. Create some completion file that we can check for correct complete installation 4. Improve reporting status of acquisition to end user --- .gitignore | 2 + .vscode/launch.json | 2 +- .vscodeignore | 12 ++ coreclr-debug/.gitignore | 4 + coreclr-debug/NuGet.config | 11 ++ coreclr-debug/dummy.cs | 13 ++ coreclr-debug/project.json | 33 +++++ package.json | 223 ++++++++++++++++++++++++++++++++++ src/coreclr-debug.ts | 243 +++++++++++++++++++++++++++++++++++++ src/omnisharpMain.ts | 4 + tsconfig.json | 2 +- 11 files changed, 547 insertions(+), 2 deletions(-) create mode 100644 .vscodeignore create mode 100644 coreclr-debug/.gitignore create mode 100644 coreclr-debug/NuGet.config create mode 100644 coreclr-debug/dummy.cs create mode 100644 coreclr-debug/project.json create mode 100644 src/coreclr-debug.ts diff --git a/.gitignore b/.gitignore index 5bf6ff89b..10415c3b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ bin node_modules out + +*.vsix diff --git a/.vscode/launch.json b/.vscode/launch.json index fe98036b6..8e2238222 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,7 @@ ], "stopOnEntry": false, "sourceMaps": true, - "outDir": "out" + "outDir": "${workspaceRoot}/out" } ] } \ No newline at end of file diff --git a/.vscodeignore b/.vscodeignore new file mode 100644 index 000000000..76287b7c1 --- /dev/null +++ b/.vscodeignore @@ -0,0 +1,12 @@ +**/*.gitignore +tsconfig.json + +src/** +**/*.map + +.vscode/** + +coreclr-debug/debugAdapters/** +coreclr-debug/bin/** +coreclr-debug/obj/** +coreclr-debug/project.lock.json \ No newline at end of file diff --git a/coreclr-debug/.gitignore b/coreclr-debug/.gitignore new file mode 100644 index 000000000..4486b48fc --- /dev/null +++ b/coreclr-debug/.gitignore @@ -0,0 +1,4 @@ +bin +obj +project.lock.json +debugAdapters \ No newline at end of file diff --git a/coreclr-debug/NuGet.config b/coreclr-debug/NuGet.config new file mode 100644 index 000000000..ae37d1c52 --- /dev/null +++ b/coreclr-debug/NuGet.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/coreclr-debug/dummy.cs b/coreclr-debug/dummy.cs new file mode 100644 index 000000000..15513fc2c --- /dev/null +++ b/coreclr-debug/dummy.cs @@ -0,0 +1,13 @@ +using System; + +namespace Dummy +{ + class Dummy + { + static void Main(string[] args) { + // empty boilerplate required by dotnet build/publish to emit an entry point + // The entrypoint created is dummy[.exe], which we rename to OpenDebugAD7[.exe] + // The generated entry point will then run OpenDebugAD7.dll for us + } + } +} \ No newline at end of file diff --git a/coreclr-debug/project.json b/coreclr-debug/project.json new file mode 100644 index 000000000..a4d8a8eb1 --- /dev/null +++ b/coreclr-debug/project.json @@ -0,0 +1,33 @@ +{ + "name": "dummy", + "compilationOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "Microsoft.VisualStudio.clrdbg": "14.0.25017-pb-2822693", + "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30217-pb-1", + "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20217-pb-1", + "NETStandard.Library": "1.0.0-rc3-23803", + "Newtonsoft.Json": "7.0.1", + "Microsoft.VisualStudio.Debugger.Interop.Portable": "1.0.1", + "System.Collections.Specialized": "4.0.1-rc3-23803", + "System.Collections.Immutable": "1.2.0-rc3-23803", + "System.Diagnostics.Process" : "4.1.0-rc3-23803", + "System.Diagnostics.StackTrace": "4.0.1-rc3-23803", + "System.Dynamic.Runtime": "4.0.11-rc3-23803", + "Microsoft.CSharp": "4.0.1-rc3-23803", + "System.Threading.Tasks.Dataflow": "4.6.0-rc3-23803", + "System.Threading.Thread": "4.0.0-rc3-23803", + "System.Xml.XDocument": "4.0.11-rc3-23803", + "System.Xml.XmlDocument": "4.0.1-rc3-23803", + "System.Xml.XmlSerializer": "4.0.11-rc3-23803", + "System.ComponentModel": "4.0.1-rc3-23803", + "System.ComponentModel.Annotations": "4.1.0-rc3-23803", + "System.ComponentModel.EventBasedAsync": "4.0.11-rc3-23803", + "System.Runtime.Serialization.Primitives": "4.1.0-rc3-23803", + "System.Net.Http": "4.0.1-rc3-23803" + }, + "frameworks": { + "dnxcore50": { } + } +} diff --git a/package.json b/package.json index ffb0e4fc4..be8ef75e3 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ }, "activationEvents": [ "onLanguage:csharp", + "onLanguage:fsharp", "onCommand:o.restart", "onCommand:o.pickProjectAndStart", "onCommand:o.restore", @@ -128,6 +129,228 @@ "language": "csharp", "path": "./snippets/csharp.json" } + ], + "debuggers": [ + { + "type": "coreclr", + "label": ".NET Core", + "enableBreakpointsFor": { "languageIds": [ "csharp", "fsharp" ] }, + + "program": "./coreclr-debug/debugAdapters/OpenDebugAD7", + "windows": { + "program": "./coreclr-debug/debugAdapters/OpenDebugAD7.exe" + }, + + "configurationAttributes": { + "launch": { + "required": [ "program", "cwd" ], + "properties": { + "program": { + "type": "string", + "description": "Path to the program (executable file) to launch. On Windows, a '.exe' suffix is appended if not specified already.", + "default": "${workspaceRoot}/bin/Debug/dnxcore50/" + }, + "cwd": { + "type": "string", + "description": "Path to the working directory of the program being debugged. Default is the current workspace.", + "default": "${workspaceRoot}" + }, + "args": { + "type": "array", + "description": "Command line arguments passed to the program.", + "items": { "type": "string" }, + "default": [ ] + }, + "stopAtEntry": { + "type": "boolean", + "description": "If true, the debugger should stop at the entry point of the target.", + "default": false + }, + "launchBrowser": { + "type": "object", + "description": "Describes options to launch a web browser as part of launch", + "default": { + "enabled": true, + "args": "${auto-detect-url}", + "windows": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "osx": { + "command": "open" + }, + "linux": { + "command": "xdg-open" + } + }, + "properties": { + "enabled": { + "type": "boolean", + "description": "Whether web browser launch is enabled", + "default": true + }, + "args": { + "type": "string", + "description": "The arguments to pass to the command to open the browser. Use ${auto-detect-url} to automatically use the address the server is listening to", + "default": "${auto-detect-url}" + }, + "osx": { + "type": "object", + "description": "OSX-specific web launch configuration options", + "default": { + "command": "open" + }, + "properties": { + "command": { + "type": "string", + "description": "The command to execute for launching the web browser", + "default": "open" + }, + "args": { + "type": "string", + "description": "The arguments to pass to the command to open the browser. Use ${auto-detect-url} to automatically use the address the server is listening to", + "default": "${auto-detect-url}" + } + } + }, + "linux": { + "type": "object", + "description": "Linux-specific web launch configuration options", + "default": { + "command": "xdg-open" + }, + "properties": { + "command": { + "type": "string", + "description": "The command to execute for launching the web browser", + "default": "xdg-open" + }, + "args": { + "type": "string", + "description": "The arguments to pass to the command to open the browser. Use ${auto-detect-url} to automatically use the address the server is listening to", + "default": "${auto-detect-url}" + } + } + }, + "windows": { + "type": "object", + "description": "Windows-specific web launch configuration options", + "default": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "properties": { + "command": { + "type": "string", + "description": "The command to execute for launching the web browser", + "default": "cmd.exe" + }, + "args": { + "type": "string", + "description": "The arguments to pass to the command to open the browser. Use ${auto-detect-url} to automatically use the address the server is listening to", + "default": "/C start ${auto-detect-url}" + } + } + } + } + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine.", + "default": { } + }, + "justMyCode": { + "type": "boolean", + "description": "Optional flag to only show user code.", + "default": true + }, + "symbolPath": { + "type": "array", + "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", + "items": { "type": "string" }, + "default": [ ] + } + } + }, + "attach": { + "required": [ ], + "properties": { + "processName": { + "type": "string", + "description": "", + "default": "The process name to attach to. If this is used, 'processId' should not be used." + }, + "processId": { + "type": "integer", + "description": "The process id to attach to. If this is used, 'processName' should not be used.", + "default": "" + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine.", + "default": { } + }, + "justMyCode": { + "type": "boolean", + "description": "Optional flag to only show user code.", + "default": true + }, + "symbolPath": { + "type": "array", + "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"~/symbols\" ]", + "items": { "type": "string" }, + "default": [ ] + } + } + } + }, + + "initialConfigurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceRoot}/bin/Debug/dnxcore50/", + "args": [ ], + "cwd": "${workspaceRoot}", + "stopAtEntry": false, + "sourceFileMap": { } + }, + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceRoot}/bin/Debug/dnxcore50/", + "args": [ ], + "cwd": "${workspaceRoot}", + "stopAtEntry": false, + "sourceFileMap": { }, + "launchBrowser": { + "enabled": true, + "args": "${auto-detect-url}", + "windows": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "osx": { + "command": "open" + }, + "linux": { + "command": "xdg-open" + } + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processName": "", + "sourceFileMap": { } + } + ] + } ] } } \ No newline at end of file diff --git a/src/coreclr-debug.ts b/src/coreclr-debug.ts new file mode 100644 index 000000000..ded6f8096 --- /dev/null +++ b/src/coreclr-debug.ts @@ -0,0 +1,243 @@ +'use strict'; + +import * as vscode from 'vscode'; +import * as child_process from 'child_process'; +import * as fs from 'fs'; +import * as path from 'path'; + +var _coreClrDebugDir: string; +var _debugAdapterDir: string; +var _channel: vscode.OutputChannel; + +export function installCoreClrDebug(context: vscode.ExtensionContext) { + _coreClrDebugDir = path.join(context.extensionPath, 'coreclr-debug'); + _debugAdapterDir = path.join(_coreClrDebugDir, 'debugAdapters'); + _channel = vscode.window.createOutputChannel('coreclr-debug'); + + if (existsSync(_debugAdapterDir)) { + console.log('.NET Core Debugger tools already installed'); + return; + } + + _channel.appendLine("Downloading and configuring the .NET Core Debugger..."); + _channel.show(vscode.ViewColumn.Three); + + spawnChildProcess('dotnet', ['restore'], _channel, _coreClrDebugDir) + .then(function() { + return spawnChildProcess('dotnet', ['publish', '-o', _debugAdapterDir], _channel, _coreClrDebugDir); + }).then(function() { + var promises: Promise[] = []; + + promises.push(renameDummyEntrypoint()); + promises = promises.concat(copyFiles(context)); + promises.push(removeLibCoreClrTraceProvider()); + + return Promise.all(promises); + }).then(function() { + _channel.appendLine('Succesfully installed .NET Core Debugger.'); + }) + .catch(function(error) { + _channel.appendLine('Error while installing .NET Core Debugger.'); + console.log(error); + }); +} + +function renameDummyEntrypoint() : Promise { + var src = path.join(_debugAdapterDir, 'dummy'); + var dest = path.join(_debugAdapterDir, 'OpenDebugAD7'); + + src += getPlatformExeExtension(); + dest += getPlatformExeExtension(); + + var promise = new Promise(function(resolve, reject) { + fs.rename(src, dest, function(err) { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + + return promise; +} + +function copyFiles(context: vscode.ExtensionContext): Promise[] { + // TODO: This method and all invocations can be removed once + // the dotnet cli tools support nuget packages with + // contentFiles metadata + // https://docs.nuget.org/create/nuspec-reference#contentfiles-with-visual-studio-2015-update-1-and-later + + var projectJson = JSON.parse(fs.readFileSync(path.join(_coreClrDebugDir, 'project.json')).toString()); + + var clrdbgId = 'Microsoft.VisualStudio.clrdbg'; + var clrdbgVersion: string = projectJson.dependencies[clrdbgId]; + + var MIEngineId = 'Microsoft.VisualStudio.clrdbg.MIEngine'; + var MIEngineVersion: string = projectJson.dependencies[MIEngineId]; + + var destRoot: string = _debugAdapterDir; + + var packagesRoot = getPackagesRoot(); + var clrdbgRoot = path.join(packagesRoot, clrdbgId, clrdbgVersion); + var MIEngineRoot = path.join(packagesRoot, MIEngineId, MIEngineVersion); + + var promises: Promise[] = []; + + function copyClrdbg(src: string, dest?: string) { promises.push(copy(path.join(clrdbgRoot, src), dest)); } + function copyMIEngine(src: string, dest?: string) { promises.push(copy(path.join(MIEngineRoot, src), dest)); } + + copyClrdbg(path.join('1033', 'clrdbg.resources.dll'), '1033'); + copyClrdbg(path.join('1033', 'vsdebugeng.impl.resources.dll'), '1033'); + copyClrdbg(path.join('1033', 'VSDebugUI.dll'), '1033'); + copyClrdbg('libclrdbg.vsdconfig'); + copyClrdbg('Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.ExpressionCompiler.vsdconfig'); + copyClrdbg('Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.ResultProvider.vsdconfig'); + copyClrdbg('version.txt'); + copyClrdbg('vsdebugeng.impl.vsdconfig'); + copyClrdbg('vsdebugeng.manimpl.vsdconfig'); + + copyMIEngine('coreclr.ad7Engine.json'); + + return promises; +} + +function removeLibCoreClrTraceProvider() : Promise +{ + var 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); + } else { + _channel.appendLine('Succesfully deleted ' + filePath) + resolve(); + } + }); + }); + } +} + +function copy(src: string, dest?: string) : Promise { + var destination = _debugAdapterDir; + if (dest) { + destination = path.join(destination, dest); + } + + return new Promise(function(resolve, reject) { + + if (!existsSync(destination)) { + fs.mkdirSync(destination); + } + + var destFile = path.join(destination, path.basename(src)) + + var sourceStream = fs.createReadStream(src); + sourceStream.on('error', reject); + var destStream = fs.createWriteStream(destFile); + destStream.on('error', reject); + destStream.on('finish', function() { + _channel.appendLine('Succesfully copied ' + src + ' to ' + destination); + resolve(); + }); + sourceStream.pipe(destStream); + }); +} + +// TODO: not currently used but may need to be used for updating. +// TODO: wrap this in try catch for i/o errors +function deleteDirectoryRecursivelySync(dirPath: string) { + if (existsSync(dirPath)) { + fs.readdirSync(dirPath).forEach(function(file, index) { + var currentPath = path.join(dirPath, file); + if (fs.lstatSync(currentPath).isDirectory()) { + deleteDirectoryRecursivelySync(currentPath); + } + else { + fs.unlinkSync(currentPath); + } + }); + fs.rmdirSync(dirPath); + } +} + +function existsSync(path: string) : boolean { + try { + fs.accessSync(path, fs.F_OK); + return true; + } catch (err) { + if (err.code === 'ENOENT') { + return false; + } else { + throw err; + } + } +} + +function getPackagesRoot() : string { + var homedir = getHomeDir(); + return path.join(homedir, '.nuget', 'packages'); +} + +function getHomeDir() : string { + switch (process.platform) { + case "win32": + return process.env['USERPROFILE']; + case "darwin": + case "linux": + return process.env['HOME']; + default: + throw new Error('Unsupported platform: ' + process.platform); + } +} + +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); + } +} + +function spawnChildProcess(process: string, args: string[], channel: vscode.OutputChannel, workingDirectory: string) : Promise { + var 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/omnisharpMain.ts b/src/omnisharpMain.ts index 5c31ee507..6ce667295 100644 --- a/src/omnisharpMain.ts +++ b/src/omnisharpMain.ts @@ -24,6 +24,7 @@ import forwardChanges from './features/changeForwarding'; import reportStatus from './features/omnisharpStatus'; import findLaunchTargets from './launchTargetFinder'; import {Disposable, ExtensionContext, DocumentSelector, languages, extensions} from 'vscode'; +import {installCoreClrDebug} from './coreclr-debug'; export function activate(context: ExtensionContext): any { @@ -75,6 +76,9 @@ export function activate(context: ExtensionContext): any { advisor.dispose(); server.stop(); })); + + // install coreclr-debug + installCoreClrDebug(context); context.subscriptions.push(...disposables); } diff --git a/tsconfig.json b/tsconfig.json index 73d8ec0fc..a6e763bd2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "noLib": true, - "target": "ES5", + "target": "es5", "module": "commonjs", "outDir": "out", "sourceMap": true From ad16289ca8f20882f3d919a01661bb7e96654171 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Tue, 23 Feb 2016 17:45:55 -0800 Subject: [PATCH 2/9] Update coreclr-debug dependencies. With this commit, the packages pulled in actually work. --- coreclr-debug/project.json | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/coreclr-debug/project.json b/coreclr-debug/project.json index a4d8a8eb1..9bc75b7b1 100644 --- a/coreclr-debug/project.json +++ b/coreclr-debug/project.json @@ -4,28 +4,28 @@ "emitEntryPoint": true }, "dependencies": { - "Microsoft.VisualStudio.clrdbg": "14.0.25017-pb-2822693", - "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30217-pb-1", - "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20217-pb-1", - "NETStandard.Library": "1.0.0-rc3-23803", + "Microsoft.VisualStudio.clrdbg": "14.0.25023-pb-2835383", + "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30223-pb-1", + "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20223-pb-1", + "NETStandard.Library": "1.0.0-rc3-23819", "Newtonsoft.Json": "7.0.1", "Microsoft.VisualStudio.Debugger.Interop.Portable": "1.0.1", - "System.Collections.Specialized": "4.0.1-rc3-23803", - "System.Collections.Immutable": "1.2.0-rc3-23803", - "System.Diagnostics.Process" : "4.1.0-rc3-23803", - "System.Diagnostics.StackTrace": "4.0.1-rc3-23803", - "System.Dynamic.Runtime": "4.0.11-rc3-23803", - "Microsoft.CSharp": "4.0.1-rc3-23803", - "System.Threading.Tasks.Dataflow": "4.6.0-rc3-23803", - "System.Threading.Thread": "4.0.0-rc3-23803", - "System.Xml.XDocument": "4.0.11-rc3-23803", - "System.Xml.XmlDocument": "4.0.1-rc3-23803", - "System.Xml.XmlSerializer": "4.0.11-rc3-23803", - "System.ComponentModel": "4.0.1-rc3-23803", - "System.ComponentModel.Annotations": "4.1.0-rc3-23803", - "System.ComponentModel.EventBasedAsync": "4.0.11-rc3-23803", - "System.Runtime.Serialization.Primitives": "4.1.0-rc3-23803", - "System.Net.Http": "4.0.1-rc3-23803" + "System.Collections.Specialized": "4.0.1-rc3-23819", + "System.Collections.Immutable": "1.2.0-rc3-23819", + "System.Diagnostics.Process" : "4.1.0-rc3-23819", + "System.Diagnostics.StackTrace": "4.0.1-rc3-23819", + "System.Dynamic.Runtime": "4.0.11-rc3-23819", + "Microsoft.CSharp": "4.0.1-rc3-23819", + "System.Threading.Tasks.Dataflow": "4.6.0-rc3-23819", + "System.Threading.Thread": "4.0.0-rc3-23819", + "System.Xml.XDocument": "4.0.11-rc3-23819", + "System.Xml.XmlDocument": "4.0.1-rc3-23819", + "System.Xml.XmlSerializer": "4.0.11-rc3-23819", + "System.ComponentModel": "4.0.1-rc3-23819", + "System.ComponentModel.Annotations": "4.1.0-rc3-23819", + "System.ComponentModel.EventBasedAsync": "4.0.11-rc3-23819", + "System.Runtime.Serialization.Primitives": "4.1.0-rc3-23819", + "System.Net.Http": "4.0.1-rc3-23819" }, "frameworks": { "dnxcore50": { } From 9d7983e1b364242939fb33f7db881085b319a54e Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Wed, 24 Feb 2016 13:16:48 -0800 Subject: [PATCH 3/9] Remove FSharp references --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index be8ef75e3..523dad05c 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ }, "activationEvents": [ "onLanguage:csharp", - "onLanguage:fsharp", "onCommand:o.restart", "onCommand:o.pickProjectAndStart", "onCommand:o.restore", @@ -130,11 +129,11 @@ "path": "./snippets/csharp.json" } ], - "debuggers": [ + "debuggers": [ { "type": "coreclr", "label": ".NET Core", - "enableBreakpointsFor": { "languageIds": [ "csharp", "fsharp" ] }, + "enableBreakpointsFor": { "languageIds": [ "csharp" ] }, "program": "./coreclr-debug/debugAdapters/OpenDebugAD7", "windows": { From 81b9a43e101bcf7880f10ee9713f8b88de7b3cc6 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Wed, 24 Feb 2016 13:27:45 -0800 Subject: [PATCH 4/9] Change var to let for file level variables --- src/coreclr-debug.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/coreclr-debug.ts b/src/coreclr-debug.ts index ded6f8096..c66a68ca0 100644 --- a/src/coreclr-debug.ts +++ b/src/coreclr-debug.ts @@ -1,3 +1,7 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; @@ -5,9 +9,9 @@ import * as child_process from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; -var _coreClrDebugDir: string; -var _debugAdapterDir: string; -var _channel: vscode.OutputChannel; +let _coreClrDebugDir: string; +let _debugAdapterDir: string; +let _channel: vscode.OutputChannel; export function installCoreClrDebug(context: vscode.ExtensionContext) { _coreClrDebugDir = path.join(context.extensionPath, 'coreclr-debug'); From a2d698463c7d5ebaa108acb9f2de344d20bb19a0 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Wed, 24 Feb 2016 14:53:20 -0800 Subject: [PATCH 5/9] Add install logging and install.complete generation 1. Add an install log log all output to our vscode OutputChannel 2. Create an install.complete file that is created only on succesfull installation of the tools. Check for the existence of this file to trigger installation --- coreclr-debug/.gitignore | 3 ++- src/coreclr-debug.ts | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/coreclr-debug/.gitignore b/coreclr-debug/.gitignore index 4486b48fc..0541f8ebe 100644 --- a/coreclr-debug/.gitignore +++ b/coreclr-debug/.gitignore @@ -1,4 +1,5 @@ bin obj project.lock.json -debugAdapters \ No newline at end of file +debugAdapters +install.log \ No newline at end of file diff --git a/src/coreclr-debug.ts b/src/coreclr-debug.ts index c66a68ca0..dd8b7099a 100644 --- a/src/coreclr-debug.ts +++ b/src/coreclr-debug.ts @@ -12,16 +12,29 @@ import * as path from 'path'; let _coreClrDebugDir: string; let _debugAdapterDir: string; let _channel: vscode.OutputChannel; +let _installLog: NodeJS.WritableStream; +let _completionFileName: string = 'install.complete'; export function installCoreClrDebug(context: vscode.ExtensionContext) { _coreClrDebugDir = path.join(context.extensionPath, 'coreclr-debug'); _debugAdapterDir = path.join(_coreClrDebugDir, 'debugAdapters'); - _channel = vscode.window.createOutputChannel('coreclr-debug'); - if (existsSync(_debugAdapterDir)) { + if (existsSync(path.join(_debugAdapterDir, _completionFileName))) { console.log('.NET Core Debugger tools already installed'); return; } + + _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() { + var proxied = _channel.append; + _channel.append = function(val: string) { + _installLog.write(val); + proxied.apply(this, arguments); + } + })(); _channel.appendLine("Downloading and configuring the .NET Core Debugger..."); _channel.show(vscode.ViewColumn.Three); @@ -37,6 +50,8 @@ export function installCoreClrDebug(context: vscode.ExtensionContext) { promises.push(removeLibCoreClrTraceProvider()); return Promise.all(promises); + }).then(function() { + return writeCompletionFile(); }).then(function() { _channel.appendLine('Succesfully installed .NET Core Debugger.'); }) @@ -46,6 +61,19 @@ export function installCoreClrDebug(context: vscode.ExtensionContext) { }); } +function writeCompletionFile() : Promise { + return new Promise(function(resolve, reject) { + fs.writeFile(path.join(_debugAdapterDir, _completionFileName), '', function(err) { + if (err) { + reject(err); + } + else { + resolve(); + } + }); + }); +} + function renameDummyEntrypoint() : Promise { var src = path.join(_debugAdapterDir, 'dummy'); var dest = path.join(_debugAdapterDir, 'OpenDebugAD7'); From f0f37f9611a59f95df90eb5ca8c4cece2e02ac00 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Wed, 24 Feb 2016 15:48:50 -0800 Subject: [PATCH 6/9] 'cleanup' --- .vscodeignore | 3 ++- coreclr-debug/project.json | 6 +++--- src/coreclr-debug.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.vscodeignore b/.vscodeignore index 76287b7c1..d8cdc7b5b 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -9,4 +9,5 @@ src/** coreclr-debug/debugAdapters/** coreclr-debug/bin/** coreclr-debug/obj/** -coreclr-debug/project.lock.json \ No newline at end of file +coreclr-debug/project.lock.json +coreclr-debug/install.log \ No newline at end of file diff --git a/coreclr-debug/project.json b/coreclr-debug/project.json index 9bc75b7b1..c823ac1c9 100644 --- a/coreclr-debug/project.json +++ b/coreclr-debug/project.json @@ -4,9 +4,9 @@ "emitEntryPoint": true }, "dependencies": { - "Microsoft.VisualStudio.clrdbg": "14.0.25023-pb-2835383", - "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30223-pb-1", - "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20223-pb-1", + "Microsoft.VisualStudio.clrdbg": "14.0.25024-pb-2837728", + "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30224-pb-1", + "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20224-pb-1", "NETStandard.Library": "1.0.0-rc3-23819", "Newtonsoft.Json": "7.0.1", "Microsoft.VisualStudio.Debugger.Interop.Portable": "1.0.1", diff --git a/src/coreclr-debug.ts b/src/coreclr-debug.ts index dd8b7099a..0a9ea0651 100644 --- a/src/coreclr-debug.ts +++ b/src/coreclr-debug.ts @@ -13,7 +13,7 @@ let _coreClrDebugDir: string; let _debugAdapterDir: string; let _channel: vscode.OutputChannel; let _installLog: NodeJS.WritableStream; -let _completionFileName: string = 'install.complete'; +const _completionFileName: string = 'install.complete'; export function installCoreClrDebug(context: vscode.ExtensionContext) { _coreClrDebugDir = path.join(context.extensionPath, 'coreclr-debug'); From 2f28f57a82f69ffd679d03960bfa1091b7e6c74b Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Wed, 24 Feb 2016 18:20:54 -0800 Subject: [PATCH 7/9] Update project.json and Remove CopyFiles The new packages use copyFiles so dotnet publish will now copy all files we need from the packages. This requires dotnet cli tools at least as new as 1.0.0.001528 (this is the windows version number at least). With contentFiles packages, we no longer need the copy routine and it's helpers. --- coreclr-debug/project.json | 4 +- src/coreclr-debug.ts | 107 ++----------------------------------- 2 files changed, 5 insertions(+), 106 deletions(-) diff --git a/coreclr-debug/project.json b/coreclr-debug/project.json index c823ac1c9..0839a4c94 100644 --- a/coreclr-debug/project.json +++ b/coreclr-debug/project.json @@ -4,8 +4,8 @@ "emitEntryPoint": true }, "dependencies": { - "Microsoft.VisualStudio.clrdbg": "14.0.25024-pb-2837728", - "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30224-pb-1", + "Microsoft.VisualStudio.clrdbg": "14.0.25024-pb-2838041", + "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30224-pb-2", "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20224-pb-1", "NETStandard.Library": "1.0.0-rc3-23819", "Newtonsoft.Json": "7.0.1", diff --git a/src/coreclr-debug.ts b/src/coreclr-debug.ts index 0a9ea0651..7d17e7103 100644 --- a/src/coreclr-debug.ts +++ b/src/coreclr-debug.ts @@ -33,7 +33,7 @@ export function installCoreClrDebug(context: vscode.ExtensionContext) { _channel.append = function(val: string) { _installLog.write(val); proxied.apply(this, arguments); - } + }; })(); _channel.appendLine("Downloading and configuring the .NET Core Debugger..."); @@ -46,7 +46,6 @@ export function installCoreClrDebug(context: vscode.ExtensionContext) { var promises: Promise[] = []; promises.push(renameDummyEntrypoint()); - promises = promises.concat(copyFiles(context)); promises.push(removeLibCoreClrTraceProvider()); return Promise.all(promises); @@ -94,46 +93,6 @@ function renameDummyEntrypoint() : Promise { return promise; } -function copyFiles(context: vscode.ExtensionContext): Promise[] { - // TODO: This method and all invocations can be removed once - // the dotnet cli tools support nuget packages with - // contentFiles metadata - // https://docs.nuget.org/create/nuspec-reference#contentfiles-with-visual-studio-2015-update-1-and-later - - var projectJson = JSON.parse(fs.readFileSync(path.join(_coreClrDebugDir, 'project.json')).toString()); - - var clrdbgId = 'Microsoft.VisualStudio.clrdbg'; - var clrdbgVersion: string = projectJson.dependencies[clrdbgId]; - - var MIEngineId = 'Microsoft.VisualStudio.clrdbg.MIEngine'; - var MIEngineVersion: string = projectJson.dependencies[MIEngineId]; - - var destRoot: string = _debugAdapterDir; - - var packagesRoot = getPackagesRoot(); - var clrdbgRoot = path.join(packagesRoot, clrdbgId, clrdbgVersion); - var MIEngineRoot = path.join(packagesRoot, MIEngineId, MIEngineVersion); - - var promises: Promise[] = []; - - function copyClrdbg(src: string, dest?: string) { promises.push(copy(path.join(clrdbgRoot, src), dest)); } - function copyMIEngine(src: string, dest?: string) { promises.push(copy(path.join(MIEngineRoot, src), dest)); } - - copyClrdbg(path.join('1033', 'clrdbg.resources.dll'), '1033'); - copyClrdbg(path.join('1033', 'vsdebugeng.impl.resources.dll'), '1033'); - copyClrdbg(path.join('1033', 'VSDebugUI.dll'), '1033'); - copyClrdbg('libclrdbg.vsdconfig'); - copyClrdbg('Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.ExpressionCompiler.vsdconfig'); - copyClrdbg('Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.ResultProvider.vsdconfig'); - copyClrdbg('version.txt'); - copyClrdbg('vsdebugeng.impl.vsdconfig'); - copyClrdbg('vsdebugeng.manimpl.vsdconfig'); - - copyMIEngine('coreclr.ad7Engine.json'); - - return promises; -} - function removeLibCoreClrTraceProvider() : Promise { var filePath = path.join(_debugAdapterDir, 'libcoreclrtraceptprovider' + getPlatformLibExtension()); @@ -146,7 +105,7 @@ function removeLibCoreClrTraceProvider() : Promise if (err) { reject(err); } else { - _channel.appendLine('Succesfully deleted ' + filePath) + _channel.appendLine('Succesfully deleted ' + filePath); resolve(); } }); @@ -154,49 +113,6 @@ function removeLibCoreClrTraceProvider() : Promise } } -function copy(src: string, dest?: string) : Promise { - var destination = _debugAdapterDir; - if (dest) { - destination = path.join(destination, dest); - } - - return new Promise(function(resolve, reject) { - - if (!existsSync(destination)) { - fs.mkdirSync(destination); - } - - var destFile = path.join(destination, path.basename(src)) - - var sourceStream = fs.createReadStream(src); - sourceStream.on('error', reject); - var destStream = fs.createWriteStream(destFile); - destStream.on('error', reject); - destStream.on('finish', function() { - _channel.appendLine('Succesfully copied ' + src + ' to ' + destination); - resolve(); - }); - sourceStream.pipe(destStream); - }); -} - -// TODO: not currently used but may need to be used for updating. -// TODO: wrap this in try catch for i/o errors -function deleteDirectoryRecursivelySync(dirPath: string) { - if (existsSync(dirPath)) { - fs.readdirSync(dirPath).forEach(function(file, index) { - var currentPath = path.join(dirPath, file); - if (fs.lstatSync(currentPath).isDirectory()) { - deleteDirectoryRecursivelySync(currentPath); - } - else { - fs.unlinkSync(currentPath); - } - }); - fs.rmdirSync(dirPath); - } -} - function existsSync(path: string) : boolean { try { fs.accessSync(path, fs.F_OK); @@ -210,26 +126,9 @@ function existsSync(path: string) : boolean { } } -function getPackagesRoot() : string { - var homedir = getHomeDir(); - return path.join(homedir, '.nuget', 'packages'); -} - -function getHomeDir() : string { - switch (process.platform) { - case "win32": - return process.env['USERPROFILE']; - case "darwin": - case "linux": - return process.env['HOME']; - default: - throw new Error('Unsupported platform: ' + process.platform); - } -} - function getPlatformExeExtension() : string { if (process.platform === 'win32') { - return '.exe' + return '.exe'; } return ''; From 5ddc12a629a25a9d33534a92652120157bddc271 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Thu, 25 Feb 2016 11:58:24 -0800 Subject: [PATCH 8/9] Update the project.json and nuget.config Pull packages from the public myget and update the dotnet invocations to use verbose output. --- coreclr-debug/NuGet.config | 3 +-- coreclr-debug/project.json | 6 +++--- src/coreclr-debug.ts | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/coreclr-debug/NuGet.config b/coreclr-debug/NuGet.config index ae37d1c52..9567dad4b 100644 --- a/coreclr-debug/NuGet.config +++ b/coreclr-debug/NuGet.config @@ -5,7 +5,6 @@ - - + diff --git a/coreclr-debug/project.json b/coreclr-debug/project.json index 0839a4c94..5524d23c4 100644 --- a/coreclr-debug/project.json +++ b/coreclr-debug/project.json @@ -4,9 +4,9 @@ "emitEntryPoint": true }, "dependencies": { - "Microsoft.VisualStudio.clrdbg": "14.0.25024-pb-2838041", - "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30224-pb-2", - "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20224-pb-1", + "Microsoft.VisualStudio.clrdbg": "14.0.25025-preview-2839567", + "Microsoft.VisualStudio.clrdbg.MIEngine": "14.0.30225-preview-2", + "Microsoft.VisualStudio.OpenDebugAD7": "1.0.20225-preview-2", "NETStandard.Library": "1.0.0-rc3-23819", "Newtonsoft.Json": "7.0.1", "Microsoft.VisualStudio.Debugger.Interop.Portable": "1.0.1", diff --git a/src/coreclr-debug.ts b/src/coreclr-debug.ts index 7d17e7103..afa8e2a56 100644 --- a/src/coreclr-debug.ts +++ b/src/coreclr-debug.ts @@ -39,9 +39,9 @@ export function installCoreClrDebug(context: vscode.ExtensionContext) { _channel.appendLine("Downloading and configuring the .NET Core Debugger..."); _channel.show(vscode.ViewColumn.Three); - spawnChildProcess('dotnet', ['restore'], _channel, _coreClrDebugDir) + spawnChildProcess('dotnet', ['--verbose', 'restore'], _channel, _coreClrDebugDir) .then(function() { - return spawnChildProcess('dotnet', ['publish', '-o', _debugAdapterDir], _channel, _coreClrDebugDir); + return spawnChildProcess('dotnet', ['--verbose', 'publish', '-o', _debugAdapterDir], _channel, _coreClrDebugDir); }).then(function() { var promises: Promise[] = []; From d7edb63e743c872b2a10e212d9ab7b9273705a98 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Thu, 25 Feb 2016 12:15:09 -0800 Subject: [PATCH 9/9] Bump vs code version to ^0.10.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 523dad05c..0647d1b69 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "tslint-microsoft-contrib": "^2.0.0" }, "engines": { - "vscode": "^0.10.1" + "vscode": "^0.10.10" }, "activationEvents": [ "onLanguage:csharp",