@@ -1838,9 +1838,9 @@ export class CppProperties {
1838
1838
curText = curText . substring ( 0 , nextNameStart2 ) ;
1839
1839
}
1840
1840
if ( this . prevSquiggleMetrics . get ( currentConfiguration . name ) === undefined ) {
1841
- this . prevSquiggleMetrics . set ( currentConfiguration . name , { PathNonExistent : 0 , PathNotAFile : 0 , PathNotADirectory : 0 , CompilerPathMissingQuotes : 0 , CompilerModeMismatch : 0 } ) ;
1841
+ this . prevSquiggleMetrics . set ( currentConfiguration . name , { PathNonExistent : 0 , PathNotAFile : 0 , PathNotADirectory : 0 , CompilerPathMissingQuotes : 0 , CompilerModeMismatch : 0 , MultiplePathsNotAllowed : 0 } ) ;
1842
1842
}
1843
- const newSquiggleMetrics : { [ key : string ] : number } = { PathNonExistent : 0 , PathNotAFile : 0 , PathNotADirectory : 0 , CompilerPathMissingQuotes : 0 , CompilerModeMismatch : 0 } ;
1843
+ const newSquiggleMetrics : { [ key : string ] : number } = { PathNonExistent : 0 , PathNotAFile : 0 , PathNotADirectory : 0 , CompilerPathMissingQuotes : 0 , CompilerModeMismatch : 0 , MultiplePathsNotAllowed : 0 } ;
1844
1844
const isWindows : boolean = os . platform ( ) === 'win32' ;
1845
1845
1846
1846
// TODO: Add other squiggles.
@@ -1867,7 +1867,7 @@ export class CppProperties {
1867
1867
}
1868
1868
1869
1869
// Check for path-related squiggles.
1870
- let paths : string [ ] = [ ] ;
1870
+ const paths : string [ ] = [ ] ;
1871
1871
let compilerPath : string | undefined ;
1872
1872
for ( const pathArray of [ currentConfiguration . browse ? currentConfiguration . browse . path : undefined ,
1873
1873
currentConfiguration . includePath , currentConfiguration . macFrameworkPath ] ) {
@@ -1895,10 +1895,7 @@ export class CppProperties {
1895
1895
compilerPath = currentConfiguration . compilerPath ;
1896
1896
}
1897
1897
1898
- // Resolve and split any environment variables
1899
- paths = this . resolveAndSplit ( paths , undefined , this . ExtendedEnvironment ) ;
1900
- compilerPath = util . resolveVariables ( compilerPath , this . ExtendedEnvironment ) . trim ( ) ;
1901
- compilerPath = this . resolvePath ( compilerPath ) ;
1898
+ compilerPath = this . resolvePath ( compilerPath ) . trim ( ) ;
1902
1899
1903
1900
// Get the start/end for properties that are file-only.
1904
1901
const forcedIncludeStart : number = curText . search ( / \s * \" f o r c e d I n c l u d e \" \s * : \s * \[ / ) ;
@@ -1961,8 +1958,7 @@ export class CppProperties {
1961
1958
let dotConfigMessage : string | undefined ;
1962
1959
1963
1960
dotConfigPath = currentConfiguration . dotConfig ;
1964
- dotConfigPath = util . resolveVariables ( dotConfigPath , this . ExtendedEnvironment ) . trim ( ) ;
1965
- dotConfigPath = this . resolvePath ( dotConfigPath ) ;
1961
+ dotConfigPath = this . resolvePath ( dotConfigPath ) . trim ( ) ;
1966
1962
// does not try resolve if the dotConfig property is empty
1967
1963
dotConfigPath = dotConfigPath !== '' ? dotConfigPath : undefined ;
1968
1964
@@ -2001,25 +1997,6 @@ export class CppProperties {
2001
1997
continue ;
2002
1998
}
2003
1999
2004
- let resolvedPath : string = this . resolvePath ( curPath ) ;
2005
- if ( ! resolvedPath ) {
2006
- continue ;
2007
- }
2008
- let pathExists : boolean = true ;
2009
- if ( this . rootUri ) {
2010
- const checkPathExists : any = util . checkPathExistsSync ( resolvedPath , this . rootUri . fsPath + path . sep , isWindows , false ) ;
2011
- pathExists = checkPathExists . pathExists ;
2012
- resolvedPath = checkPathExists . path ;
2013
- }
2014
- // Normalize path separators.
2015
- if ( path . sep === "/" ) {
2016
- resolvedPath = resolvedPath . replace ( / \\ / g, path . sep ) ;
2017
- } else {
2018
- resolvedPath = resolvedPath . replace ( / \/ / g, path . sep ) ;
2019
- }
2020
-
2021
- // Iterate through the text and apply squiggles.
2022
-
2023
2000
// Escape the path string for literal use in a regular expression
2024
2001
// Need to escape any quotes to match the original text
2025
2002
let escapedPath : string = curPath . replace ( / " / g, '\\"' ) ;
@@ -2030,6 +2007,42 @@ export class CppProperties {
2030
2007
const pattern : RegExp = new RegExp ( `"[^"]*?(?<="|;)${ escapedPath } (?="|;).*?"` , "g" ) ;
2031
2008
const configMatches : string [ ] | null = curText . match ( pattern ) ;
2032
2009
2010
+ const expandedPaths : string [ ] = this . resolveAndSplit ( [ curPath ] , undefined , this . ExtendedEnvironment , true , true ) ;
2011
+ const incorrectExpandedPaths : string [ ] = [ ] ;
2012
+
2013
+ if ( expandedPaths . length <= 0 ) {
2014
+ continue ;
2015
+ }
2016
+
2017
+ if ( this . rootUri ) {
2018
+ for ( const [ index , expandedPath ] of expandedPaths . entries ( ) ) {
2019
+ if ( expandedPath . includes ( "${workspaceFolder}" ) ) {
2020
+ expandedPaths [ index ] = this . resolvePath ( expandedPath , false ) ;
2021
+ } else {
2022
+ expandedPaths [ index ] = this . resolvePath ( expandedPath ) ;
2023
+ }
2024
+
2025
+ const checkPathExists : any = util . checkPathExistsSync ( expandedPaths [ index ] , this . rootUri . fsPath + path . sep , isWindows , false ) ;
2026
+ if ( ! checkPathExists . pathExists ) {
2027
+ // If there are multiple paths, store any non-existing paths to squiggle later on.
2028
+ incorrectExpandedPaths . push ( expandedPaths [ index ] ) ;
2029
+ }
2030
+ }
2031
+ }
2032
+
2033
+ const pathExists : boolean = incorrectExpandedPaths . length === 0 ;
2034
+
2035
+ for ( const [ index , expandedPath ] of expandedPaths . entries ( ) ) {
2036
+ // Normalize path separators.
2037
+ if ( path . sep === "/" ) {
2038
+ expandedPaths [ index ] = expandedPath . replace ( / \\ / g, path . sep ) ;
2039
+ } else {
2040
+ expandedPaths [ index ] = expandedPath . replace ( / \/ / g, path . sep ) ;
2041
+ }
2042
+ }
2043
+
2044
+ // Iterate through the text and apply squiggles.
2045
+
2033
2046
let globPath : boolean = false ;
2034
2047
const asteriskPosition = curPath . indexOf ( "*" ) ;
2035
2048
if ( asteriskPosition !== - 1 ) {
@@ -2041,6 +2054,7 @@ export class CppProperties {
2041
2054
}
2042
2055
}
2043
2056
}
2057
+
2044
2058
if ( configMatches && ! globPath ) {
2045
2059
let curOffset : number = 0 ;
2046
2060
let endOffset : number = 0 ;
@@ -2050,29 +2064,57 @@ export class CppProperties {
2050
2064
if ( curOffset >= compilerPathStart && curOffset <= compilerPathEnd ) {
2051
2065
continue ;
2052
2066
}
2053
- let message : string ;
2067
+ let message : string = "" ;
2054
2068
if ( ! pathExists ) {
2055
2069
if ( curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd
2056
- && ! path . isAbsolute ( resolvedPath ) ) {
2070
+ && ! path . isAbsolute ( expandedPaths [ 0 ] ) ) {
2057
2071
continue ; // Skip the error, because it could be resolved recursively.
2058
2072
}
2059
- message = localize ( 'cannot.find2' , "Cannot find \"{0}\"." , resolvedPath ) ;
2073
+ let badPath = "" ;
2074
+ if ( incorrectExpandedPaths . length > 0 ) {
2075
+ badPath = incorrectExpandedPaths . map ( s => `"${ s } "` ) . join ( ', ' ) ;
2076
+ } else {
2077
+ badPath = `"${ expandedPaths [ 0 ] } "` ;
2078
+ }
2079
+ message = localize ( 'cannot.find2' , "Cannot find {0}" , badPath ) ;
2060
2080
newSquiggleMetrics . PathNonExistent ++ ;
2061
2081
} else {
2062
2082
// Check for file versus path mismatches.
2063
2083
if ( ( curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd ) ||
2064
- ( curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd ) ) {
2065
- if ( util . checkFileExistsSync ( resolvedPath ) ) {
2066
- continue ;
2084
+ ( curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd ) ) {
2085
+ if ( expandedPaths . length > 1 ) {
2086
+ message = localize ( "multiple.paths.not.allowed" , "Multiple paths are not allowed." ) ;
2087
+ newSquiggleMetrics . MultiplePathsNotAllowed ++ ;
2088
+ } else {
2089
+ const resolvedPath = this . resolvePath ( expandedPaths [ 0 ] ) ;
2090
+ if ( util . checkFileExistsSync ( resolvedPath ) ) {
2091
+ continue ;
2092
+ }
2093
+
2094
+ message = localize ( "path.is.not.a.file" , "Path is not a file: {0}" , expandedPaths [ 0 ] ) ;
2095
+ newSquiggleMetrics . PathNotAFile ++ ;
2067
2096
}
2068
- message = localize ( "path.is.not.a.file" , "Path is not a file: {0}" , resolvedPath ) ;
2069
- newSquiggleMetrics . PathNotAFile ++ ;
2070
2097
} else {
2071
- if ( util . checkDirectoryExistsSync ( resolvedPath ) ) {
2098
+ const mismatchedPaths : string [ ] = [ ] ;
2099
+ for ( const expandedPath of expandedPaths ) {
2100
+ const resolvedPath = this . resolvePath ( expandedPath ) ;
2101
+ if ( ! util . checkDirectoryExistsSync ( resolvedPath ) ) {
2102
+ mismatchedPaths . push ( expandedPath ) ;
2103
+ }
2104
+ }
2105
+
2106
+ let badPath = "" ;
2107
+ if ( mismatchedPaths . length > 1 ) {
2108
+ badPath = mismatchedPaths . map ( s => `"${ s } "` ) . join ( ', ' ) ;
2109
+ message = localize ( 'paths.are.not.directories' , "Paths are not directories: {0}" , badPath ) ;
2110
+ newSquiggleMetrics . PathNotADirectory ++ ;
2111
+ } else if ( mismatchedPaths . length === 1 ) {
2112
+ badPath = `"${ mismatchedPaths [ 0 ] } "` ;
2113
+ message = localize ( 'path.is.not.a.directory' , "Path is not a directory: {0}" , badPath ) ;
2114
+ newSquiggleMetrics . PathNotADirectory ++ ;
2115
+ } else {
2072
2116
continue ;
2073
2117
}
2074
- message = localize ( "path.is.not.a.directory" , "Path is not a directory: {0}" , resolvedPath ) ;
2075
- newSquiggleMetrics . PathNotADirectory ++ ;
2076
2118
}
2077
2119
}
2078
2120
const diagnostic : vscode . Diagnostic = new vscode . Diagnostic (
@@ -2092,7 +2134,7 @@ export class CppProperties {
2092
2134
endOffset = curOffset + curMatch . length ;
2093
2135
let message : string ;
2094
2136
if ( ! pathExists ) {
2095
- message = localize ( 'cannot.find2' , "Cannot find \"{0}\"." , resolvedPath ) ;
2137
+ message = localize ( 'cannot.find2' , "Cannot find \"{0}\"." , expandedPaths [ 0 ] ) ;
2096
2138
newSquiggleMetrics . PathNonExistent ++ ;
2097
2139
const diagnostic : vscode . Diagnostic = new vscode . Diagnostic (
2098
2140
new vscode . Range ( document . positionAt ( envTextStartOffSet + curOffset ) ,
@@ -2128,6 +2170,9 @@ export class CppProperties {
2128
2170
if ( newSquiggleMetrics . CompilerModeMismatch !== this . prevSquiggleMetrics . get ( currentConfiguration . name ) ?. CompilerModeMismatch ) {
2129
2171
changedSquiggleMetrics . CompilerModeMismatch = newSquiggleMetrics . CompilerModeMismatch ;
2130
2172
}
2173
+ if ( newSquiggleMetrics . MultiplePathsNotAllowed !== this . prevSquiggleMetrics . get ( currentConfiguration . name ) ?. MultiplePathsNotAllowed ) {
2174
+ changedSquiggleMetrics . MultiplePathsNotAllowed = newSquiggleMetrics . MultiplePathsNotAllowed ;
2175
+ }
2131
2176
if ( Object . keys ( changedSquiggleMetrics ) . length > 0 ) {
2132
2177
telemetry . logLanguageServerEvent ( "ConfigSquiggles" , undefined , changedSquiggleMetrics ) ;
2133
2178
}
0 commit comments