Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ out
install.*

*.vsix

obj/
bin/
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main'
key_url: 'https://packages.microsoft.com/keys/microsoft.asc'
packages:
- g++-4.9
- libsecret-1-dev
- dotnet-sdk-2.0.2

install:
- npm install
Expand Down
41 changes: 38 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,51 @@
]
},
{
"name": "Launch Tests",
"name": "Launch Unit Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
"args": [
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/unitTests"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/test/**/*.js"
]
},
{
"name": "Launch singleCsproj Workspace Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceRoot}/test/integrationTests/testAssets/singleCsproj",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/test/**/*.js"
]
},
{
"name": "Launch slnWithCsproj Workspace Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/test/**/*.js"
]
}
]
}
}
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"**/node_modules": true,
"out/": true
},

"csharp.suppressDotnetRestoreNotification": true,

"tslint.rulesDirectory": "node_modules/tslint-microsoft-contrib",
"typescript.tsdk": "./node_modules/typescript/lib"
Expand Down
14 changes: 13 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@
"vscode:prepublish": "tsc -p ./",
"compile": "tsc -p ./ && gulp tslint",
"watch": "tsc -watch -p ./",
"test": "node ./node_modules/vscode/bin/test",
"test": "npm-run-all test:unit test:integration",
"test:unit": "cross-env CODE_TESTS_PATH=./out/test/unitTests npm run test:runInVsCode",
"test:integration": "npm-run-all test:integration:*",
"test:integration:singleCsproj": "cross-env OSVC_SUITE=singleCsproj npm run test:runSuiteInVsCode",
"test:integration:slnWithCsproj": "cross-env OSVC_SUITE=slnWithCsproj npm run test:runSuiteInVsCode",
"test:runSuiteInVsCode": "cross-env CODE_TESTS_PATH=./out/test/integrationTests CODE_TESTS_WORKSPACE=./test/integrationTests/testAssets/$OSVC_SUITE npm run test:runInVsCode",
"test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js",
"postinstall": "node ./node_modules/vscode/bin/install"
},
"dependencies": {
Expand All @@ -46,18 +52,24 @@
},
"devDependencies": {
"@types/chai": "^3.4.34",
"@types/chai-arrays": "^1.0.2",
"@types/fs-extra": "4.0.3",
"@types/mkdirp": "^0.3.29",
"@types/mocha": "^2.2.32",
"@types/node": "^6.0.40",
"@types/semver": "^5.3.30",
"@types/tmp": "0.0.32",
"async-file": "^2.0.2",
"chai": "^3.5.0",
"chai-arrays": "^2.0.0",
"chai-fs": "^1.0.0",
"cross-env": "^5.1.1",
"del": "^2.0.2",
"gulp": "^3.9.1",
"gulp-mocha": "^2.1.3",
"gulp-tslint": "^4.3.0",
"mocha": "^2.3.3",
"npm-run-all": "^4.1.1",
"plist": "^2.0.1",
"tslint": "^3.15.1",
"tslint-microsoft-contrib": "^2.0.12",
Expand Down
93 changes: 55 additions & 38 deletions src/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@

import * as fs from 'fs-extra';
import * as path from 'path';
import * as vscode from 'vscode';
import * as protocol from './omnisharp/protocol';
import * as serverUtils from './omnisharp/utils';
import * as tasks from 'vscode-tasks';
import * as util from './common';
import * as vscode from 'vscode';

import { OmniSharpServer } from './omnisharp/server';
import * as serverUtils from './omnisharp/utils';
import * as protocol from './omnisharp/protocol';
import { tolerantParse } from './json';
import * as util from './common';

export class AssetGenerator {
public rootPath: string;
public workspaceFolder: vscode.WorkspaceFolder;
public vscodeFolder: string;
public tasksJsonPath: string;
public launchJsonPath: string;
Expand All @@ -26,13 +27,33 @@ export class AssetGenerator {
private executableName: string;
private configurationName: string;

public constructor(workspaceInfo: protocol.WorkspaceInformationResponse, rootPath: string = vscode.workspace.rootPath) {
if (rootPath === null || rootPath === undefined) {
throw new Error('rootPath must set.');
public constructor(workspaceInfo: protocol.WorkspaceInformationResponse, workspaceFolder: vscode.WorkspaceFolder = undefined) {
if (workspaceFolder) {
this.workspaceFolder = workspaceFolder;
}
else {
let resourcePath: string = undefined;

if (!resourcePath && workspaceInfo.Cake) {
resourcePath = workspaceInfo.Cake.Path;
}

this.rootPath = rootPath;
this.vscodeFolder = path.join(this.rootPath, '.vscode');
if (!resourcePath && workspaceInfo.ScriptCs) {
resourcePath = workspaceInfo.ScriptCs.Path;
}

if (!resourcePath && workspaceInfo.DotNet && workspaceInfo.DotNet.Projects.length > 0) {
resourcePath = workspaceInfo.DotNet.Projects[0].Path;
}

if (!resourcePath && workspaceInfo.MsBuild) {
resourcePath = workspaceInfo.MsBuild.SolutionPath;
}

this.workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(resourcePath));
}

this.vscodeFolder = path.join(this.workspaceFolder.uri.fsPath, '.vscode');
this.tasksJsonPath = path.join(this.vscodeFolder, 'tasks.json');
this.launchJsonPath = path.join(this.vscodeFolder, 'launch.json');

Expand Down Expand Up @@ -132,15 +153,15 @@ export class AssetGenerator {
let result = '${workspaceFolder}';

if (this.projectPath) {
result = path.join(result, path.relative(this.rootPath, this.projectPath));
result = path.join(result, path.relative(this.workspaceFolder.uri.fsPath, this.projectPath));
}

result = path.join(result, `bin/${this.configurationName}/${this.targetFramework}/${this.executableName}`);

return result;
}

private computeWorkingDirectory() : string {
private computeWorkingDirectory(): string {
if (!this.hasProject) {
// If there's no target project data, use a placeholder for the path.
return '${workspaceFolder}';
Expand All @@ -149,7 +170,7 @@ export class AssetGenerator {
let result = '${workspaceFolder}';

if (this.projectPath) {
result = path.join(result, path.relative(this.rootPath, this.projectPath));
result = path.join(result, path.relative(this.workspaceFolder.uri.fsPath, this.projectPath));
}

return result;
Expand Down Expand Up @@ -179,7 +200,7 @@ export class AssetGenerator {
private createBuildTaskDescription(): tasks.TaskDescription {
let buildPath = '';
if (this.hasProject) {
buildPath = path.join('${workspaceFolder}', path.relative(this.rootPath, this.projectFilePath));
buildPath = path.join('${workspaceFolder}', path.relative(this.workspaceFolder.uri.fsPath, this.projectFilePath));
}

return {
Expand Down Expand Up @@ -235,7 +256,7 @@ export function createWebLaunchConfiguration(programPath: string, workingDirecto
}`;
}

export function createLaunchConfiguration(programPath: string, workingDirectory: string): string {
export function createLaunchConfiguration(programPath: string, workingDirectory: string): string {
return `
{
"name": ".NET Core Launch (console)",
Expand Down Expand Up @@ -378,13 +399,13 @@ interface PromptItem extends vscode.MessageItem {
result: PromptResult;
}

function promptToAddAssets() {
function promptToAddAssets(workspaceFolder: vscode.WorkspaceFolder) {
return new Promise<PromptResult>((resolve, reject) => {
const yesItem: PromptItem = { title: 'Yes', result: PromptResult.Yes };
const noItem: PromptItem = { title: 'Not Now', result: PromptResult.No, isCloseAffordance: true };
const disableItem: PromptItem = { title: "Don't Ask Again", result: PromptResult.Disable };

const projectName = path.basename(vscode.workspace.rootPath);
const projectName = path.basename(workspaceFolder.uri.fsPath);

vscode.window.showWarningMessage(
`Required assets to build and debug are missing from '${projectName}'. Add them?`, disableItem, noItem, yesItem)
Expand Down Expand Up @@ -463,7 +484,7 @@ export enum AddAssetResult {

export function addAssetsIfNecessary(server: OmniSharpServer): Promise<AddAssetResult> {
return new Promise<AddAssetResult>((resolve, reject) => {
if (!vscode.workspace.rootPath) {
if (!vscode.workspace.workspaceFolders) {
return resolve(AddAssetResult.NotApplicable);
}

Expand All @@ -476,7 +497,7 @@ export function addAssetsIfNecessary(server: OmniSharpServer): Promise<AddAssetR
return resolve(AddAssetResult.NotApplicable);
}

promptToAddAssets().then(result => {
promptToAddAssets(generator.workspaceFolder).then(result => {
if (result === PromptResult.Disable) {
return resolve(AddAssetResult.Disable);
}
Expand Down Expand Up @@ -546,24 +567,20 @@ function shouldGenerateAssets(generator: AssetGenerator) {
});
}

export function generateAssets(server: OmniSharpServer) {
serverUtils.requestWorkspaceInformation(server).then(info => {
if (protocol.containsDotNetCoreProjects(info)) {
const generator = new AssetGenerator(info);
getOperations(generator).then(operations => {
if (hasAddOperations(operations)) {
shouldGenerateAssets(generator).then(res => {
if (res) {
fs.ensureDir(generator.vscodeFolder, err => {
addAssets(generator, operations);
});
}
});
}
});
}
else {
vscode.window.showErrorMessage("Could not locate .NET Core project. Assets were not generated.");
export async function generateAssets(server: OmniSharpServer) {
let workspaceInformation = await serverUtils.requestWorkspaceInformation(server);
if (protocol.containsDotNetCoreProjects(workspaceInformation)) {
const generator = new AssetGenerator(workspaceInformation);
let operations = await getOperations(generator);
if (hasAddOperations(operations)) {
let doGenerateAssets = await shouldGenerateAssets(generator);
if (doGenerateAssets) {
await fs.ensureDir(generator.vscodeFolder);
await addAssets(generator, operations);
}
}
});
}
else {
await vscode.window.showErrorMessage("Could not locate .NET Core project. Assets were not generated.");
}
}
12 changes: 7 additions & 5 deletions src/configurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as fs from 'fs-extra';
import * as path from 'path';
import { parse } from 'jsonc-parser';
import { OmniSharpServer } from './omnisharp/server';
import * as serverUtils from './omnisharp/utils';
import * as vscode from 'vscode';

import { AssetGenerator, addTasksJsonIfNecessary, createAttachConfiguration, createLaunchConfiguration, createWebLaunchConfiguration } from './assets';

import { OmniSharpServer } from './omnisharp/server';
import { containsDotNetCoreProjects } from './omnisharp/protocol';
import { AssetGenerator, addTasksJsonIfNecessary, createLaunchConfiguration, createAttachConfiguration, createWebLaunchConfiguration } from './assets';
import { isSubfolderOf } from './common';
import { parse } from 'jsonc-parser';

export class CSharpConfigurationProvider implements vscode.DebugConfigurationProvider {
private server: OmniSharpServer;
Expand Down Expand Up @@ -101,7 +103,7 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro
/**
* Try to add all missing attributes to the debug configuration being launched.
*/
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
// vsdbg does the error checking
return config;
}
Expand Down
35 changes: 22 additions & 13 deletions src/coreclr-debug/activate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,49 @@
*--------------------------------------------------------------------------------------------*/
'use strict';

import * as vscode from 'vscode';
import * as debugInstall from './install';
import * as os from 'os';
import TelemetryReporter from 'vscode-extension-telemetry';
import * as vscode from 'vscode';

import { CoreClrDebugUtil, DotnetInfo, } from './util';
import * as debugInstall from './install';

import { Logger } from './../logger';
import { PlatformInformation } from './../platform';
import TelemetryReporter from 'vscode-extension-telemetry';

let _debugUtil: CoreClrDebugUtil = null;
let _reporter: TelemetryReporter = null;
let _logger: Logger = null;

export function activate(thisExtension : vscode.Extension<any>, context: vscode.ExtensionContext, reporter: TelemetryReporter, logger: Logger, channel: vscode.OutputChannel) {
export async function activate(thisExtension : vscode.Extension<any>, context: vscode.ExtensionContext, reporter: TelemetryReporter, logger: Logger, channel: vscode.OutputChannel) {
_debugUtil = new CoreClrDebugUtil(context.extensionPath, logger);
_reporter = reporter;
_logger = logger;

if (!CoreClrDebugUtil.existsSync(_debugUtil.debugAdapterDir())) {
PlatformInformation.GetCurrent().then((info) => {
if (info.architecture !== "x86_64") {
if (info.isWindows() && info.architecture === "x86") {
let platformInformation: PlatformInformation;

try {
platformInformation = await PlatformInformation.GetCurrent();
}
catch (err) {
// Somehow we couldn't figure out the platform we are on
logger.appendLine("[ERROR]: C# Extension failed to install the debugger package");
showInstallErrorMessage(channel);
}

if (platformInformation) {
if (platformInformation.architecture !== "x86_64") {
if (platformInformation.isWindows() && platformInformation.architecture === "x86") {
logger.appendLine(`[WARNING]: x86 Windows is not currently supported by the .NET Core debugger. Debugging will not be available.`);
} else {
logger.appendLine(`[WARNING]: Processor architecture '${info.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`);
logger.appendLine(`[WARNING]: Processor architecture '${platformInformation.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`);
}
} else {
logger.appendLine("[ERROR]: C# Extension failed to install the debugger package");
showInstallErrorMessage(channel);
}
}, (err) => {
// Somehow we couldn't figure out the platform we are on
logger.appendLine("[ERROR]: C# Extension failed to install the debugger package");
showInstallErrorMessage(channel);
});
}
} else if (!CoreClrDebugUtil.existsSync(_debugUtil.installCompleteFilePath())) {
completeDebuggerInstall(logger, channel);
}
Expand Down
Loading