@@ -31,14 +31,10 @@ export class CppBuildTask extends Task {
3131export 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