Skip to content

Commit df8523e

Browse files
author
Elaheh Rashedi
authored
"F5" using the correct build task (#6420)
* shows details correctly * change default name * generating unique names * lint errors * lint errors * modify resolvetask * modify details
1 parent 7d7b898 commit df8523e

File tree

2 files changed

+84
-31
lines changed

2 files changed

+84
-31
lines changed

Extension/src/Debugger/configurationProvider.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as debugUtils from './utils';
77
import * as os from 'os';
88
import * as path from 'path';
99
import * as vscode from 'vscode';
10-
import { CppBuildTaskDefinition } from '../LanguageServer/cppBuildTaskProvider';
10+
import { CppBuildTask, CppBuildTaskDefinition } from '../LanguageServer/cppBuildTaskProvider';
1111
import * as util from '../common';
1212
import * as fs from 'fs';
1313
import * as Telemetry from '../telemetry';
@@ -113,25 +113,49 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
113113
* Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder.
114114
*/
115115
async provideDebugConfigurations(folder?: vscode.WorkspaceFolder, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration[]> {
116-
let buildTasks: vscode.Task[] = await cppBuildTaskProvider.getTasks(true);
117-
if (buildTasks.length === 0) {
118-
return Promise.resolve(this.provider.getInitialConfigurations(this.type));
119-
}
120116
const defaultConfig: vscode.DebugConfiguration = this.provider.getInitialConfigurations(this.type).find((config: any) =>
121117
isDebugLaunchStr(config.name) && config.request === "launch");
122118
console.assert(defaultConfig, "Could not find default debug configuration.");
123119

124120
const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation();
125121
const platform: string = platformInfo.platform;
126122

123+
// Import the tasks from tasks.json file.
124+
const buildTasksJson: CppBuildTask[] = await cppBuildTaskProvider.getJsonTasks();
125+
126+
// Provide detected tasks by cppBuildTaskProvider.
127+
const buildTasksDetected: CppBuildTask[] = await cppBuildTaskProvider.getTasks(true);
128+
129+
// Rename the provided tasks that has same name as tasks in tasks.json.
130+
const buildTasksDetectedRename: CppBuildTask[] = buildTasksDetected.map(taskDetected => {
131+
for (const taskJson of buildTasksJson) {
132+
if ((taskDetected.definition.label as string) === (taskJson.definition.label as string)) {
133+
taskDetected.name = cppBuildTaskProvider.provideUniqueTaskLabel(taskJson.definition.label, buildTasksJson);
134+
taskDetected.definition.label = taskDetected.name;
135+
break;
136+
}
137+
}
138+
return taskDetected;
139+
});
140+
141+
let buildTasks: CppBuildTask[] = [];
142+
buildTasks = buildTasks.concat(buildTasksJson, buildTasksDetectedRename);
143+
144+
if (buildTasks.length === 0) {
145+
return Promise.resolve(this.provider.getInitialConfigurations(this.type));
146+
}
147+
148+
if (buildTasks.length === 0) {
149+
return Promise.resolve(this.provider.getInitialConfigurations(this.type));
150+
}
127151
// Filter out build tasks that don't match the currently selected debug configuration type.
128-
buildTasks = buildTasks.filter((task: vscode.Task) => {
152+
buildTasks = buildTasks.filter((task: CppBuildTask) => {
129153
if (defaultConfig.name.startsWith("(Windows) ")) {
130-
if (task.name.startsWith("C/C++: cl.exe")) {
154+
if ((task.definition.command as string).includes("cl.exe")) {
131155
return true;
132156
}
133157
} else {
134-
if (!task.name.startsWith("C/C++: cl.exe")) {
158+
if (!(task.definition.command as string).includes("cl.exe")) {
135159
return true;
136160
}
137161
}
@@ -153,7 +177,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
153177
newConfig.program = platform === "win32" ? exeName + ".exe" : exeName;
154178
// Add the "detail" property to show the compiler path in QuickPickItem.
155179
// This property will be removed before writing the DebugConfiguration in launch.json.
156-
newConfig.detail = definition.command;
180+
newConfig.detail = task.detail ? task.detail : definition.command;
157181

158182
return new Promise<vscode.DebugConfiguration>(resolve => {
159183
if (platform === "darwin") {

Extension/src/LanguageServer/cppBuildTaskProvider.ts

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,10 @@ export class CppBuildTask extends Task {
3131
export class CppBuildTaskProvider implements TaskProvider {
3232
static CppBuildScriptType: string = 'cppbuild';
3333
static CppBuildSourceStr: string = "C/C++";
34-
private tasks: CppBuildTask[] | undefined;
3534

3635
constructor() { }
3736

3837
public async provideTasks(): Promise<CppBuildTask[]> {
39-
if (this.tasks) {
40-
return this.tasks;
41-
}
4238
return this.getTasks(false);
4339
}
4440

@@ -47,17 +43,14 @@ export class CppBuildTaskProvider implements TaskProvider {
4743
const execution: ProcessExecution | ShellExecution | CustomExecution | undefined = _task.execution;
4844
if (!execution) {
4945
const definition: CppBuildTaskDefinition = <any>_task.definition;
50-
_task = this.getTask(definition.command, false, definition.args ? definition.args : [], definition);
46+
_task = this.getTask(definition.command, false, definition.args ? definition.args : [], definition, _task.detail);
5147
return _task;
5248
}
5349
return undefined;
5450
}
5551

5652
// Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension.
5753
public async getTasks(appendSourceToName: boolean): Promise<CppBuildTask[]> {
58-
if (this.tasks !== undefined) {
59-
return this.tasks;
60-
}
6154
const editor: TextEditor | undefined = window.activeTextEditor;
6255
const emptyTasks: CppBuildTask[] = [];
6356
if (!editor) {
@@ -149,14 +142,11 @@ export class CppBuildTaskProvider implements TaskProvider {
149142
if (userCompilerPath) {
150143
result.push(this.getTask(userCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs));
151144
}
152-
153145
return result;
154146
}
155147

156-
private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => {
148+
private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition, detail?: string) => Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition, detail?: string) => {
157149
const compilerPathBase: string = path.basename(compilerPath);
158-
const taskLabel: string = ((appendSourceToName && !compilerPathBase.startsWith(CppBuildTaskProvider.CppBuildSourceStr)) ?
159-
CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file";
160150
const isCl: boolean = compilerPathBase === "cl.exe";
161151
// Double-quote the command if it is not already double-quoted.
162152
let resolvedcompilerPath: string = isCl ? compilerPathBase : compilerPath;
@@ -165,6 +155,8 @@ export class CppBuildTaskProvider implements TaskProvider {
165155
}
166156

167157
if (!definition) {
158+
const taskLabel: string = ((appendSourceToName && !compilerPathBase.startsWith(CppBuildTaskProvider.CppBuildSourceStr)) ?
159+
CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file";
168160
const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}');
169161
const isWindows: boolean = os.platform() === 'win32';
170162
let args: string[] = isCl ? ['/Zi', '/EHsc', '/Fe:', filePath + '.exe', '${file}'] : ['-g', '${file}', '-o', filePath + (isWindows ? '.exe' : '')];
@@ -192,38 +184,58 @@ export class CppBuildTaskProvider implements TaskProvider {
192184
}
193185

194186
const scope: TaskScope = TaskScope.Workspace;
195-
const task: CppBuildTask = new Task(definition, scope, taskLabel, CppBuildTaskProvider.CppBuildSourceStr,
187+
const task: CppBuildTask = new Task(definition, scope, definition.label, CppBuildTaskProvider.CppBuildSourceStr,
196188
new CustomExecution(async (): Promise<Pseudoterminal> =>
197189
// When the task is executed, this callback will run. Here, we setup for running the task.
198190
new CustomBuildTaskTerminal(resolvedcompilerPath, definition ? definition.args : [], definition ? definition.options : undefined)
199191
), isCl ? '$msCompile' : '$gcc');
200192

201193
task.group = TaskGroup.Build;
202-
task.detail = "compiler: " + resolvedcompilerPath;
194+
task.detail = detail ? detail : "compiler: " + resolvedcompilerPath;
203195

204196
return task;
205197
};
206198

199+
public async getJsonTasks(): Promise<CppBuildTask[]> {
200+
const rawJson: any = await this.getRawTasksJson();
201+
const rawTasksJson: any = (!rawJson.tasks) ? new Array() : rawJson.tasks;
202+
const buildTasksJson: CppBuildTask[] = rawTasksJson.map((task: any) => {
203+
const definition: CppBuildTaskDefinition = {
204+
type: task.type,
205+
label: task.label,
206+
command: task.command,
207+
args: task.args,
208+
options: task.options
209+
};
210+
const cppBuildTask: CppBuildTask = new Task(definition, TaskScope.Workspace, task.label, "C/C++");
211+
cppBuildTask.detail = task.detail;
212+
return cppBuildTask;
213+
});
214+
return buildTasksJson;
215+
}
216+
207217
public async ensureBuildTaskExists(taskLabel: string): Promise<void> {
208218
const rawTasksJson: any = await this.getRawTasksJson();
209-
210-
// Ensure that the task exists in the user's task.json. Task will not be found otherwise.
211219
if (!rawTasksJson.tasks) {
212220
rawTasksJson.tasks = new Array();
213221
}
214-
// Find or create the task which should be created based on the selected "debug configuration".
215-
let selectedTask: CppBuildTask | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel);
222+
// Ensure that the task exists in the user's task.json. Task will not be found otherwise.
223+
let selectedTask: any = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel);
216224
if (selectedTask) {
217225
return;
218226
}
219227

228+
// Create the task which should be created based on the selected "debug configuration".
220229
const buildTasks: CppBuildTask[] = await this.getTasks(true);
221-
selectedTask = buildTasks.find(task => task.name === taskLabel);
230+
const normalizedLabel: string = (taskLabel.indexOf("ver(") !== -1) ? taskLabel.slice(0, taskLabel.indexOf("ver(")).trim() : taskLabel;
231+
selectedTask = buildTasks.find(task => task.name === normalizedLabel);
222232
console.assert(selectedTask);
223233
if (!selectedTask) {
224234
throw new Error("Failed to get selectedTask in ensureBuildTaskExists()");
235+
} else {
236+
selectedTask.definition.label = taskLabel;
237+
selectedTask.name = taskLabel;
225238
}
226-
227239
rawTasksJson.version = "2.0.0";
228240

229241
// Modify the current default task
@@ -272,6 +284,23 @@ export class CppBuildTaskProvider implements TaskProvider {
272284
return;
273285
}
274286

287+
// Provide a unique name for a newly defined tasks, which is different from tasks' names in tasks.json.
288+
public provideUniqueTaskLabel(label: string, buildTasksJson: CppBuildTask[]): string {
289+
const taskNameDictionary: {[key: string]: any} = {};
290+
buildTasksJson.forEach(task => {
291+
taskNameDictionary[task.definition.label] = {};
292+
});
293+
let newLabel: string = label;
294+
let version: number = 0;
295+
do {
296+
version = version + 1;
297+
newLabel = label + ` ver(${version})`;
298+
299+
} while (taskNameDictionary[newLabel]);
300+
301+
return newLabel;
302+
}
303+
275304
private getLaunchJsonPath(): string | undefined {
276305
return util.getJsonPath("launch.json");
277306
}
@@ -280,12 +309,12 @@ export class CppBuildTaskProvider implements TaskProvider {
280309
return util.getJsonPath("tasks.json");
281310
}
282311

283-
private getRawLaunchJson(): Promise<any> {
312+
public getRawLaunchJson(): Promise<any> {
284313
const path: string | undefined = this.getLaunchJsonPath();
285314
return util.getRawJson(path);
286315
}
287316

288-
private getRawTasksJson(): Promise<any> {
317+
public getRawTasksJson(): Promise<any> {
289318
const path: string | undefined = this.getTasksJsonPath();
290319
return util.getRawJson(path);
291320
}

0 commit comments

Comments
 (0)