Skip to content

Commit 6420465

Browse files
Update asset generation to be workspace folder aware
Asset generation now uses the workspace information from OmniSharp to determine which workspace folder to use in the face of a multi-root workspace.
1 parent fa293d2 commit 6420465

File tree

2 files changed

+56
-27
lines changed

2 files changed

+56
-27
lines changed

src/assets.ts

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { OmniSharpServer } from './omnisharp/server';
1515
import { tolerantParse } from './json';
1616

1717
export class AssetGenerator {
18-
public rootPath: string;
18+
public workspaceFolder: vscode.WorkspaceFolder;
1919
public vscodeFolder: string;
2020
public tasksJsonPath: string;
2121
public launchJsonPath: string;
@@ -27,13 +27,33 @@ export class AssetGenerator {
2727
private executableName: string;
2828
private configurationName: string;
2929

30-
public constructor(workspaceInfo: protocol.WorkspaceInformationResponse, rootPath: string = vscode.workspace.rootPath) {
31-
if (rootPath === null || rootPath === undefined) {
32-
throw new Error('rootPath must set.');
30+
public constructor(workspaceInfo: protocol.WorkspaceInformationResponse, workspaceFolder: vscode.WorkspaceFolder = undefined) {
31+
if (workspaceFolder) {
32+
this.workspaceFolder = workspaceFolder;
33+
}
34+
else {
35+
let resourcePath: string = undefined;
36+
37+
if (!resourcePath && workspaceInfo.Cake) {
38+
resourcePath = workspaceInfo.Cake.Path;
39+
}
40+
41+
if (!resourcePath && workspaceInfo.ScriptCs) {
42+
resourcePath = workspaceInfo.ScriptCs.Path;
43+
}
44+
45+
if (!resourcePath && workspaceInfo.DotNet && workspaceInfo.DotNet.Projects.length > 0) {
46+
resourcePath = workspaceInfo.DotNet.Projects[0].Path;
47+
}
48+
49+
if (!resourcePath && workspaceInfo.MsBuild) {
50+
resourcePath = workspaceInfo.MsBuild.SolutionPath;
51+
}
52+
53+
this.workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(resourcePath));
3354
}
3455

35-
this.rootPath = rootPath;
36-
this.vscodeFolder = path.join(this.rootPath, '.vscode');
56+
this.vscodeFolder = path.join(this.workspaceFolder.uri.fsPath, '.vscode');
3757
this.tasksJsonPath = path.join(this.vscodeFolder, 'tasks.json');
3858
this.launchJsonPath = path.join(this.vscodeFolder, 'launch.json');
3959

@@ -133,15 +153,15 @@ export class AssetGenerator {
133153
let result = '${workspaceFolder}';
134154

135155
if (this.projectPath) {
136-
result = path.join(result, path.relative(this.rootPath, this.projectPath));
156+
result = path.join(result, path.relative(this.workspaceFolder.uri.fsPath, this.projectPath));
137157
}
138158

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

141161
return result;
142162
}
143163

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

152172
if (this.projectPath) {
153-
result = path.join(result, path.relative(this.rootPath, this.projectPath));
173+
result = path.join(result, path.relative(this.workspaceFolder.uri.fsPath, this.projectPath));
154174
}
155175

156176
return result;
@@ -180,7 +200,7 @@ export class AssetGenerator {
180200
private createBuildTaskDescription(): tasks.TaskDescription {
181201
let buildPath = '';
182202
if (this.hasProject) {
183-
buildPath = path.join('${workspaceFolder}', path.relative(this.rootPath, this.projectFilePath));
203+
buildPath = path.join('${workspaceFolder}', path.relative(this.workspaceFolder.uri.fsPath, this.projectFilePath));
184204
}
185205

186206
return {
@@ -236,7 +256,7 @@ export function createWebLaunchConfiguration(programPath: string, workingDirecto
236256
}`;
237257
}
238258

239-
export function createLaunchConfiguration(programPath: string, workingDirectory: string): string {
259+
export function createLaunchConfiguration(programPath: string, workingDirectory: string): string {
240260
return `
241261
{
242262
"name": ".NET Core Launch (console)",
@@ -379,13 +399,13 @@ interface PromptItem extends vscode.MessageItem {
379399
result: PromptResult;
380400
}
381401

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

388-
const projectName = path.basename(vscode.workspace.rootPath);
408+
const projectName = path.basename(workspaceFolder.uri.fsPath);
389409

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

465485
export function addAssetsIfNecessary(server: OmniSharpServer): Promise<AddAssetResult> {
466486
return new Promise<AddAssetResult>((resolve, reject) => {
467-
if (!vscode.workspace.rootPath) {
487+
if (!vscode.workspace.workspaceFolders) {
468488
return resolve(AddAssetResult.NotApplicable);
469489
}
470490

@@ -477,7 +497,7 @@ export function addAssetsIfNecessary(server: OmniSharpServer): Promise<AddAssetR
477497
return resolve(AddAssetResult.NotApplicable);
478498
}
479499

480-
promptToAddAssets().then(result => {
500+
promptToAddAssets(generator.workspaceFolder).then(result => {
481501
if (result === PromptResult.Disable) {
482502
return resolve(AddAssetResult.Disable);
483503
}

test/unitTests/assets.test.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,27 @@
55

66
import * as path from 'path';
77
import * as protocol from '../../src/omnisharp/protocol';
8+
import * as vscode from 'vscode';
89

910
import { AssetGenerator } from '../../src/assets';
1011
import { parse } from 'jsonc-parser';
1112
import { should } from 'chai';
1213

14+
function createMockWorkspaceFolder(rootPath: string) : vscode.WorkspaceFolder {
15+
return {
16+
uri: vscode.Uri.file(rootPath),
17+
name: undefined,
18+
index: undefined
19+
}
20+
}
21+
1322
suite("Asset generation: project.json", () => {
1423
suiteSetup(() => should());
1524

1625
test("Create tasks.json for project opened in workspace", () => {
1726
let rootPath = path.resolve('testRoot');
1827
let info = createDotNetWorkspaceInformation(rootPath, 'testApp.dll', 'netcoreapp1.0');
19-
let generator = new AssetGenerator(info, rootPath);
28+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
2029
let tasksJson = generator.createTasksConfiguration();
2130
let buildPath = tasksJson.tasks[0].args[1];
2231

@@ -28,7 +37,7 @@ suite("Asset generation: project.json", () => {
2837
test("Create tasks.json for nested project opened in workspace", () => {
2938
let rootPath = path.resolve('testRoot');
3039
let info = createDotNetWorkspaceInformation(path.join(rootPath, 'nested'), 'testApp.dll', 'netcoreapp1.0');
31-
let generator = new AssetGenerator(info, rootPath);
40+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
3241
let tasksJson = generator.createTasksConfiguration();
3342
let buildPath = tasksJson.tasks[0].args[1];
3443

@@ -40,7 +49,7 @@ suite("Asset generation: project.json", () => {
4049
test("Create launch.json for project opened in workspace", () => {
4150
let rootPath = path.resolve('testRoot');
4251
let info = createDotNetWorkspaceInformation(rootPath, 'testApp.dll', 'netcoreapp1.0');
43-
let generator = new AssetGenerator(info, rootPath);
52+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
4453
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true });
4554
let programPath = launchJson[0].program;
4655

@@ -52,7 +61,7 @@ suite("Asset generation: project.json", () => {
5261
test("Create launch.json for nested project opened in workspace", () => {
5362
let rootPath = path.resolve('testRoot');
5463
let info = createDotNetWorkspaceInformation(path.join(rootPath, 'nested'), 'testApp.dll', 'netcoreapp1.0');
55-
let generator = new AssetGenerator(info, rootPath);
64+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
5665
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true });
5766
let programPath = launchJson[0].program;
5867

@@ -64,7 +73,7 @@ suite("Asset generation: project.json", () => {
6473
test("Create launch.json for web project opened in workspace", () => {
6574
let rootPath = path.resolve('testRoot');
6675
let info = createDotNetWorkspaceInformation(rootPath, 'testApp.dll', 'netcoreapp1.0');
67-
let generator = new AssetGenerator(info, rootPath);
76+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
6877
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true });
6978
let programPath = launchJson[0].program;
7079

@@ -76,7 +85,7 @@ suite("Asset generation: project.json", () => {
7685
test("Create launch.json for nested web project opened in workspace", () => {
7786
let rootPath = path.resolve('testRoot');
7887
let info = createDotNetWorkspaceInformation(path.join(rootPath, 'nested'), 'testApp.dll', 'netcoreapp1.0');
79-
let generator = new AssetGenerator(info, rootPath);
88+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
8089
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true });
8190
let programPath = launchJson[0].program;
8291

@@ -124,7 +133,7 @@ suite("Asset generation: csproj", () => {
124133
test("Create tasks.json for project opened in workspace", () => {
125134
let rootPath = path.resolve('testRoot');
126135
let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'testApp.csproj'), 'testApp', 'netcoreapp1.0');
127-
let generator = new AssetGenerator(info, rootPath);
136+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
128137
let tasksJson = generator.createTasksConfiguration();
129138
let buildPath = tasksJson.tasks[0].args[1];
130139

@@ -136,7 +145,7 @@ suite("Asset generation: csproj", () => {
136145
test("Create tasks.json for nested project opened in workspace", () => {
137146
let rootPath = path.resolve('testRoot');
138147
let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'nested', 'testApp.csproj'), 'testApp', 'netcoreapp1.0');
139-
let generator = new AssetGenerator(info, rootPath);
148+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
140149
let tasksJson = generator.createTasksConfiguration();
141150
let buildPath = tasksJson.tasks[0].args[1];
142151

@@ -148,7 +157,7 @@ suite("Asset generation: csproj", () => {
148157
test("Create launch.json for project opened in workspace", () => {
149158
let rootPath = path.resolve('testRoot');
150159
let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'testApp.csproj'), 'testApp', 'netcoreapp1.0');
151-
let generator = new AssetGenerator(info, rootPath);
160+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
152161
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true });
153162
let programPath = launchJson[0].program;
154163

@@ -160,7 +169,7 @@ suite("Asset generation: csproj", () => {
160169
test("Create launch.json for nested project opened in workspace", () => {
161170
let rootPath = path.resolve('testRoot');
162171
let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'nested', 'testApp.csproj'), 'testApp', 'netcoreapp1.0');
163-
let generator = new AssetGenerator(info, rootPath);
172+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
164173
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true });
165174
let programPath = launchJson[0].program;
166175

@@ -172,7 +181,7 @@ suite("Asset generation: csproj", () => {
172181
test("Create launch.json for web project opened in workspace", () => {
173182
let rootPath = path.resolve('testRoot');
174183
let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'testApp.csproj'), 'testApp', 'netcoreapp1.0');
175-
let generator = new AssetGenerator(info, rootPath);
184+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
176185
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true });
177186
let programPath = launchJson[0].program;
178187

@@ -184,7 +193,7 @@ suite("Asset generation: csproj", () => {
184193
test("Create launch.json for nested web project opened in workspace", () => {
185194
let rootPath = path.resolve('testRoot');
186195
let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'nested', 'testApp.csproj'), 'testApp', 'netcoreapp1.0');
187-
let generator = new AssetGenerator(info, rootPath);
196+
let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath));
188197
let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true });
189198
let programPath = launchJson[0].program;
190199

0 commit comments

Comments
 (0)