@@ -408,9 +408,18 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
408408 // Generating a task is async, therefore we must *await* *all* map(task => config) Promises to resolve.
409409 let configs : CppDebugConfiguration [ ] = [ ] ;
410410 if ( buildTasks . length !== 0 ) {
411- configs = await Promise . all ( buildTasks . map < Promise < CppDebugConfiguration > > ( async task => {
411+ configs = ( await Promise . all ( buildTasks . map < Promise < CppDebugConfiguration | undefined > > ( async task => {
412412 const definition : CppBuildTaskDefinition = task . definition as CppBuildTaskDefinition ;
413413 const compilerPath : string = definition . command ;
414+ // Filter out the tasks that has an invalid compiler path.
415+ const compilerPathExists : boolean = path . isAbsolute ( compilerPath ) ?
416+ // Absolute path, just check if it exists
417+ await util . checkFileExists ( compilerPath ) :
418+ // Non-absolute. Check on $PATH
419+ ( ( await util . whichAsync ( compilerPath ) ) !== undefined ) ;
420+ if ( ! compilerPathExists ) {
421+ logger . getOutputChannelLogger ( ) . appendLine ( localize ( 'compiler.path.not.exists' , "Unable to find {0}. {1} task is ignored." , compilerPath , definition . label ) ) ;
422+ }
414423 const compilerName : string = path . basename ( compilerPath ) ;
415424 const newConfig : CppDebugConfiguration = { ...defaultTemplateConfig } ; // Copy enumerables and properties
416425 newConfig . existing = false ;
@@ -439,20 +448,24 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
439448 const isCl : boolean = compilerName === "cl.exe" ;
440449 newConfig . cwd = isWindows && ! isCl && ! process . env . PATH ?. includes ( path . dirname ( compilerPath ) ) ? path . dirname ( compilerPath ) : "${fileDirname}" ;
441450
442- return new Promise < CppDebugConfiguration > ( resolve => {
451+ return new Promise < CppDebugConfiguration | undefined > ( async resolve => {
443452 if ( platformInfo . platform === "darwin" ) {
444453 return resolve ( newConfig ) ;
445454 } else {
446455 let debuggerName : string ;
447456 if ( compilerName . startsWith ( "clang" ) ) {
448457 newConfig . MIMode = "lldb" ;
449- debuggerName = "lldb-mi" ;
450- // Search for clang-8, clang-10, etc.
451- if ( ( compilerName !== "clang-cl.exe" ) && ( compilerName !== "clang-cpp.exe" ) ) {
452- const suffixIndex : number = compilerName . indexOf ( "-" ) ;
453- if ( suffixIndex !== - 1 ) {
454- const suffix : string = compilerName . substring ( suffixIndex ) ;
455- debuggerName += suffix ;
458+ if ( isWindows ) {
459+ debuggerName = "lldb" ;
460+ } else {
461+ debuggerName = "lldb-mi" ;
462+ // Search for clang-8, clang-10, etc.
463+ if ( ( compilerName !== "clang-cl.exe" ) && ( compilerName !== "clang-cpp.exe" ) ) {
464+ const suffixIndex : number = compilerName . indexOf ( "-" ) ;
465+ if ( suffixIndex !== - 1 ) {
466+ const suffix : string = compilerName . substring ( suffixIndex ) ;
467+ debuggerName += suffix ;
468+ }
456469 }
457470 }
458471 newConfig . type = DebuggerType . cppdbg ;
@@ -468,22 +481,27 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
468481 }
469482 const compilerDirname : string = path . dirname ( compilerPath ) ;
470483 const debuggerPath : string = path . join ( compilerDirname , debuggerName ) ;
471- if ( isWindows ) {
484+
485+ // Check if debuggerPath exists.
486+ if ( await util . checkFileExists ( debuggerPath ) ) {
472487 newConfig . miDebuggerPath = debuggerPath ;
473- return resolve ( newConfig ) ;
488+ } else if ( ( await util . whichAsync ( debuggerName ) ) !== undefined ) {
489+ // Check if debuggerName exists on $PATH
490+ newConfig . miDebuggerPath = debuggerName ;
474491 } else {
475- fs . stat ( debuggerPath , ( err , stats : fs . Stats ) => {
476- if ( ! err && stats && stats . isFile ( ) ) {
477- newConfig . miDebuggerPath = debuggerPath ;
478- } else {
479- newConfig . miDebuggerPath = path . join ( "/usr" , "bin" , debuggerName ) ;
480- }
481- return resolve ( newConfig ) ;
482- } ) ;
492+ // Try the usr path for non-windows platforms.
493+ const usrDebuggerPath : string = path . join ( "/usr" , "bin" , debuggerName ) ;
494+ if ( ! isWindows && await util . checkFileExists ( usrDebuggerPath ) ) {
495+ newConfig . miDebuggerPath = usrDebuggerPath ;
496+ } else {
497+ logger . getOutputChannelLogger ( ) . appendLine ( localize ( 'debugger.path.not.exists' , "Unable to find the {0} debugger. The debug configuration for {1} is ignored." , `\" ${ debuggerName } \"` , compilerName ) ) ;
498+ return resolve ( undefined ) ;
499+ }
483500 }
501+ return resolve ( newConfig ) ;
484502 }
485503 } ) ;
486- } ) ) ;
504+ } ) ) ) . filter ( ( item ) : item is CppDebugConfiguration => ! ! item ) ;
487505 }
488506 configs . push ( defaultTemplateConfig ) ;
489507 const existingConfigs : CppDebugConfiguration [ ] | undefined = this . getLaunchConfigs ( folder , type ) ?. map ( config => {
0 commit comments