Skip to content

Commit 03b89c4

Browse files
authored
Add ConfigurationProvider API, ${workspaceRoot} -> ${workspaceFolder} (#1801)
* Updating tasks.json schema New tasks schema from 0.1.0 to 2.0.0 * Updating tasks.json and initialConfigurations package.json's initialConfiguraitons have been deprecated. It uses DebugConfigurationProvider instead. C# extension uses generate assets initially to create launch.json and tasks.json. However, if a user desides to dismiss the message and generate via f5, the prompt will initiate the DebugConfigurationProvider. * Adding ConfigurationProvider ${workspaceRoot} is now ${workspaceFolder} ConfigurationProvider activates on f5. This will also trigger generating a tasks file. tasks args are now 'build <path>', updating tests for these changes. * API requires October 2017 Drop (1.18) * Fixing version requirement error * Addressing PR issues * Detect older tasks.json Checking if folder.uri.fsPath is a subfolder of GetSolutionPathOrFolder to generate assets. * Fixing PR issues * Upgrading fs-extra for promises * Rewriting package.json for activation events * Reverting start activationEvents Removing empty if and assuming paths have consistent casing.
1 parent 9c09ab7 commit 03b89c4

File tree

13 files changed

+469
-325
lines changed

13 files changed

+469
-325
lines changed

debugger-launchjson.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ This will create a task that runs `dotnet build`. You can read more about tasks
2020
## Program
2121
The program field is set to the path of the application dll or .NET Core host executable to launch.
2222

23-
This property normally takes the form: "${workspaceRoot}/bin/Debug/\<target-framework\>/\<project-name.dll\>".
23+
This property normally takes the form: "${workspaceFolder}/bin/Debug/\<target-framework\>/\<project-name.dll\>".
2424

25-
Example: `"${workspaceRoot}/bin/Debug/netcoreapp1.1/MyProject.dll"`
25+
Example: `"${workspaceFolder}/bin/Debug/netcoreapp1.1/MyProject.dll"`
2626

2727
Where:
2828

@@ -102,7 +102,7 @@ then add the pipeTransport field folloing this schema:
102102
"pipeProgram": "ssh",
103103
"pipeArgs": [ "-T", "ExampleAccount@ExampleTargetComputer" ],
104104
"debuggerPath": "~/vsdbg/vsdbg",
105-
"pipeCwd": "${workspaceRoot}",
105+
"pipeCwd": "${workspaceFolder}",
106106
"quoteArgs": true
107107
}
108108

debugger.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ If your code has multiple projects or you would rather generate these files by h
6666
"configurations": [
6767
{
6868
...
69-
"program": "${workspaceRoot}/MyLaunchingProject/bin/Debug/netcoreapp1.0/MyLaunchingProject.dll",
69+
"program": "${workspaceFolder}/MyLaunchingProject/bin/Debug/netcoreapp1.0/MyLaunchingProject.dll",
7070

7171
##### 4: Start debugging
7272
Your project is now all set. Set a breakpoint or two where you want to stop, click the debugger play button (or press <kbd>F5</kbd>) and you are off.

package.json

Lines changed: 41 additions & 89 deletions
Large diffs are not rendered by default.

src/assets.ts

Lines changed: 100 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class AssetGenerator {
4646

4747
// First, we'll check for .NET Core .csproj projects.
4848
if (workspaceInfo.MsBuild && workspaceInfo.MsBuild.Projects) {
49-
const executableMSBuildProjects = findExecutableMSBuildProjects(workspaceInfo.MsBuild.Projects);
49+
const executableMSBuildProjects = protocol.findExecutableMSBuildProjects(workspaceInfo.MsBuild.Projects);
5050

5151
const targetMSBuildProject = executableMSBuildProjects.length > 0
5252
? executableMSBuildProjects[0]
@@ -64,7 +64,7 @@ export class AssetGenerator {
6464
}
6565

6666
// Next, we'll try looking for project.json projects.
67-
const executableProjects = findExecutableProjectJsonProjects(workspaceInfo.DotNet.Projects, configurationName);
67+
const executableProjects = protocol.findExecutableProjectJsonProjects(workspaceInfo.DotNet.Projects, configurationName);
6868

6969
// TODO: We arbitrarily pick the first executable project that we find. This will need
7070
// revisiting when we project a "start up project" selector.
@@ -126,10 +126,10 @@ export class AssetGenerator {
126126
private computeProgramPath() {
127127
if (!this.hasProject) {
128128
// If there's no target project data, use a placeholder for the path.
129-
return '${workspaceRoot}/bin/Debug/<insert-target-framework-here>/<insert-project-name-here>.dll';
129+
return '${workspaceFolder}/bin/Debug/<insert-target-framework-here>/<insert-project-name-here>.dll';
130130
}
131131

132-
let result = '${workspaceRoot}';
132+
let result = '${workspaceFolder}';
133133

134134
if (this.projectPath) {
135135
result = path.join(result, path.relative(this.rootPath, this.projectPath));
@@ -143,10 +143,10 @@ export class AssetGenerator {
143143
private computeWorkingDirectory() : string {
144144
if (!this.hasProject) {
145145
// If there's no target project data, use a placeholder for the path.
146-
return '${workspaceRoot}';
146+
return '${workspaceFolder}';
147147
}
148148

149-
let result = '${workspaceRoot}';
149+
let result = '${workspaceFolder}';
150150

151151
if (this.projectPath) {
152152
result = path.join(result, path.relative(this.rootPath, this.projectPath));
@@ -155,84 +155,19 @@ export class AssetGenerator {
155155
return result;
156156
}
157157

158-
private createLaunchConfiguration(): string{
159-
return `
160-
{
161-
"name": ".NET Core Launch (console)",
162-
"type": "coreclr",
163-
"request": "launch",
164-
"preLaunchTask": "build",
165-
// If you have changed target frameworks, make sure to update the program path.
166-
"program": "${util.convertNativePathToPosix(this.computeProgramPath())}",
167-
"args": [],
168-
"cwd": "${util.convertNativePathToPosix(this.computeWorkingDirectory())}",
169-
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
170-
"console": "internalConsole",
171-
"stopAtEntry": false,
172-
"internalConsoleOptions": "openOnSessionStart"
173-
}`;
174-
}
175-
176-
private createWebLaunchConfiguration(): string {
177-
return `
178-
{
179-
"name": ".NET Core Launch (web)",
180-
"type": "coreclr",
181-
"request": "launch",
182-
"preLaunchTask": "build",
183-
// If you have changed target frameworks, make sure to update the program path.
184-
"program": "${util.convertNativePathToPosix(this.computeProgramPath())}",
185-
"args": [],
186-
"cwd": "${util.convertNativePathToPosix(this.computeWorkingDirectory())}",
187-
"stopAtEntry": false,
188-
"internalConsoleOptions": "openOnSessionStart",
189-
"launchBrowser": {
190-
"enabled": true,
191-
"args": "\${auto-detect-url}",
192-
"windows": {
193-
"command": "cmd.exe",
194-
"args": "/C start \${auto-detect-url}"
195-
},
196-
"osx": {
197-
"command": "open"
198-
},
199-
"linux": {
200-
"command": "xdg-open"
201-
}
202-
},
203-
"env": {
204-
"ASPNETCORE_ENVIRONMENT": "Development"
205-
},
206-
"sourceFileMap": {
207-
"/Views": "\${workspaceRoot}/Views"
208-
}
209-
}`;
210-
}
211-
212-
// AttachConfiguration
213-
private createAttachConfiguration(): string {
214-
return `
215-
{
216-
"name": ".NET Core Attach",
217-
"type": "coreclr",
218-
"request": "attach",
219-
"processId": "\${command:pickProcess}"
220-
}`;
221-
}
222-
223158
public createLaunchJson(isWebProject: boolean): string {
224159
if (!isWebProject) {
225-
const launchConfigurationsMassaged: string = indentJsonString(this.createLaunchConfiguration());
226-
const attachConfigurationsMassaged: string = indentJsonString(this.createAttachConfiguration());
160+
const launchConfigurationsMassaged: string = indentJsonString(createLaunchConfiguration(this.computeProgramPath(), this.computeWorkingDirectory()));
161+
const attachConfigurationsMassaged: string = indentJsonString(createAttachConfiguration());
227162
return `
228163
[
229164
${launchConfigurationsMassaged},
230165
${attachConfigurationsMassaged}
231166
]`;
232167
}
233168
else {
234-
const webLaunchConfigurationsMassaged: string = indentJsonString(this.createWebLaunchConfiguration());
235-
const attachConfigurationsMassaged: string = indentJsonString(this.createAttachConfiguration());
169+
const webLaunchConfigurationsMassaged: string = indentJsonString(createWebLaunchConfiguration(this.computeProgramPath(), this.computeWorkingDirectory()));
170+
const attachConfigurationsMassaged: string = indentJsonString(createAttachConfiguration());
236171
return `
237172
[
238173
${webLaunchConfigurationsMassaged},
@@ -244,69 +179,91 @@ export class AssetGenerator {
244179
private createBuildTaskDescription(): tasks.TaskDescription {
245180
let buildPath = '';
246181
if (this.hasProject) {
247-
buildPath = path.join('${workspaceRoot}', path.relative(this.rootPath, this.projectFilePath));
182+
buildPath = path.join('${workspaceFolder}', path.relative(this.rootPath, this.projectFilePath));
248183
}
249184

250185
return {
251186
taskName: 'build',
252-
args: [util.convertNativePathToPosix(buildPath)],
253-
isBuildCommand: true,
187+
command: 'dotnet',
188+
type: 'process',
189+
args: ['build', util.convertNativePathToPosix(buildPath)],
254190
problemMatcher: '$msCompile'
255191
};
256192
}
257193

258194
public createTasksConfiguration(): tasks.TaskConfiguration {
259195
return {
260-
version: '0.1.0',
261-
command: 'dotnet',
262-
isShellCommand: true,
263-
args: [],
196+
version: "2.0.0",
264197
tasks: [this.createBuildTaskDescription()]
265198
};
266199
}
267200
}
268201

269-
function findExecutableMSBuildProjects(projects: protocol.MSBuildProject[]) {
270-
let result: protocol.MSBuildProject[] = [];
271-
272-
projects.forEach(project => {
273-
if (project.IsExe && protocol.findNetCoreAppTargetFramework(project) !== undefined) {
274-
result.push(project);
202+
export function createWebLaunchConfiguration(programPath: string, workingDirectory: string): string {
203+
return `
204+
{
205+
"name": ".NET Core Launch (web)",
206+
"type": "coreclr",
207+
"request": "launch",
208+
"preLaunchTask": "build",
209+
// If you have changed target frameworks, make sure to update the program path.
210+
"program": "${util.convertNativePathToPosix(programPath)}",
211+
"args": [],
212+
"cwd": "${util.convertNativePathToPosix(workingDirectory)}",
213+
"stopAtEntry": false,
214+
"internalConsoleOptions": "openOnSessionStart",
215+
"launchBrowser": {
216+
"enabled": true,
217+
"args": "\${auto-detect-url}",
218+
"windows": {
219+
"command": "cmd.exe",
220+
"args": "/C start \${auto-detect-url}"
221+
},
222+
"osx": {
223+
"command": "open"
224+
},
225+
"linux": {
226+
"command": "xdg-open"
275227
}
276-
});
277-
278-
return result;
228+
},
229+
"env": {
230+
"ASPNETCORE_ENVIRONMENT": "Development"
231+
},
232+
"sourceFileMap": {
233+
"/Views": "\${workspaceFolder}/Views"
234+
}
235+
}`;
279236
}
280237

281-
function findExecutableProjectJsonProjects(projects: protocol.DotNetProject[], configurationName: string) {
282-
let result: protocol.DotNetProject[] = [];
283-
284-
projects.forEach(project => {
285-
project.Configurations.forEach(configuration => {
286-
if (configuration.Name === configurationName && configuration.EmitEntryPoint === true) {
287-
if (project.Frameworks.length > 0) {
288-
result.push(project);
289-
}
290-
}
291-
});
292-
});
293-
294-
return result;
238+
export function createLaunchConfiguration(programPath: string, workingDirectory: string): string {
239+
return `
240+
{
241+
"name": ".NET Core Launch (console)",
242+
"type": "coreclr",
243+
"request": "launch",
244+
"preLaunchTask": "build",
245+
// If you have changed target frameworks, make sure to update the program path.
246+
"program": "${util.convertNativePathToPosix(programPath)}",
247+
"args": [],
248+
"cwd": "${util.convertNativePathToPosix(workingDirectory)}",
249+
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
250+
"console": "internalConsole",
251+
"stopAtEntry": false,
252+
"internalConsoleOptions": "openOnSessionStart"
253+
}`;
295254
}
296255

297-
function containsDotNetCoreProjects(workspaceInfo: protocol.WorkspaceInformationResponse) {
298-
if (workspaceInfo.DotNet && findExecutableProjectJsonProjects(workspaceInfo.DotNet.Projects, 'Debug').length > 0) {
299-
return true;
300-
}
301-
302-
if (workspaceInfo.MsBuild && findExecutableMSBuildProjects(workspaceInfo.MsBuild.Projects).length > 0) {
303-
return true;
304-
}
305-
306-
return false;
256+
// AttachConfiguration
257+
export function createAttachConfiguration(): string {
258+
return `
259+
{
260+
"name": ".NET Core Attach",
261+
"type": "coreclr",
262+
"request": "attach",
263+
"processId": "\${command:pickProcess}"
264+
}`;
307265
}
308266

309-
310267
interface Operations {
311268
addTasksJson?: boolean;
312269
updateTasksJson?: boolean;
@@ -322,30 +279,44 @@ function getOperations(generator: AssetGenerator) {
322279
getLaunchOperations(generator.launchJsonPath, operations));
323280
}
324281

282+
/**
283+
* Will return old (version=0.1.0) or new (version=2.0.0) tasks. If there are any of them, do not
284+
* write over the tasks.json.
285+
*/
325286
function getBuildTasks(tasksConfiguration: tasks.TaskConfiguration): tasks.TaskDescription[] {
326287
let result: tasks.TaskDescription[] = [];
327288

328-
function findBuildTask(tasksDescriptions: tasks.TaskDescription[]) {
329-
if (tasksDescriptions) {
330-
const buildTask = tasksDescriptions.find(td => td.isBuildCommand);
331-
if (buildTask !== undefined) {
332-
result.push(buildTask);
333-
}
289+
const tasksV1: string = "0.1.0";
290+
const tasksV2: string = "2.0.0";
291+
292+
function findBuildTask(version: string, tasksDescriptions: tasks.TaskDescription[]) {
293+
let buildTask = undefined;
294+
// Find the old tasks
295+
if (version === tasksV1 && tasksDescriptions) {
296+
buildTask = tasksDescriptions.find(td => td.isBuildCommand);
297+
}
298+
// Find the new tasks
299+
else if (version === tasksV2 && tasksDescriptions) {
300+
buildTask = tasksDescriptions.find(td => td.group === 'build');
301+
}
302+
303+
if (buildTask !== undefined) {
304+
result.push(buildTask);
334305
}
335306
}
336307

337-
findBuildTask(tasksConfiguration.tasks);
308+
findBuildTask(tasksConfiguration.version, tasksConfiguration.tasks);
338309

339310
if (tasksConfiguration.windows) {
340-
findBuildTask(tasksConfiguration.windows.tasks);
311+
findBuildTask(tasksConfiguration.version, tasksConfiguration.windows.tasks);
341312
}
342313

343314
if (tasksConfiguration.osx) {
344-
findBuildTask(tasksConfiguration.osx.tasks);
315+
findBuildTask(tasksConfiguration.version, tasksConfiguration.osx.tasks);
345316
}
346317

347318
if (tasksConfiguration.linux) {
348-
findBuildTask(tasksConfiguration.linux.tasks);
319+
findBuildTask(tasksConfiguration.version, tasksConfiguration.linux.tasks);
349320
}
350321

351322
return result;
@@ -421,7 +392,7 @@ function promptToAddAssets() {
421392
});
422393
}
423394

424-
function addTasksJsonIfNecessary(generator: AssetGenerator, operations: Operations) {
395+
export function addTasksJsonIfNecessary(generator: AssetGenerator, operations: Operations) {
425396
return new Promise<void>((resolve, reject) => {
426397
if (!operations.addTasksJson) {
427398
return resolve();
@@ -498,7 +469,7 @@ export function addAssetsIfNecessary(server: OmniSharpServer): Promise<AddAssetR
498469

499470
serverUtils.requestWorkspaceInformation(server).then(info => {
500471
// If there are no .NET Core projects, we won't bother offering to add assets.
501-
if (containsDotNetCoreProjects(info)) {
472+
if (protocol.containsDotNetCoreProjects(info)) {
502473
const generator = new AssetGenerator(info);
503474
return getOperations(generator).then(operations => {
504475
if (!hasAddOperations(operations)) {
@@ -577,7 +548,7 @@ function shouldGenerateAssets(generator: AssetGenerator) {
577548

578549
export function generateAssets(server: OmniSharpServer) {
579550
serverUtils.requestWorkspaceInformation(server).then(info => {
580-
if (containsDotNetCoreProjects(info)) {
551+
if (protocol.containsDotNetCoreProjects(info)) {
581552
const generator = new AssetGenerator(info);
582553
getOperations(generator).then(operations => {
583554
if (hasAddOperations(operations)) {

src/common.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,20 @@ export function deleteInstallFile(type: InstallFileType): Promise<void> {
167167
export function convertNativePathToPosix(pathString: string): string {
168168
let parts = pathString.split(path.sep);
169169
return parts.join(path.posix.sep);
170+
}
171+
172+
/**
173+
* This function checks to see if a subfolder is part of folder.
174+
*
175+
* Assumes subfolder and folder are absolute paths and have consistent casing.
176+
*
177+
* @param subfolder subfolder to check if it is part of the folder parameter
178+
* @param folder folder to check aganist
179+
*/
180+
export function isSubfolderOf(subfolder: string, folder: string): boolean {
181+
const subfolderArray: string[] = subfolder.split(path.sep);
182+
const folderArray: string[] = folder.split(path.sep);
183+
184+
// Check to see that every sub directory in subfolder exists in folder.
185+
return subfolderArray.length <= folderArray.length && subfolderArray.every((subpath, index) => folderArray[index] === subpath);
170186
}

0 commit comments

Comments
 (0)