@@ -1057,7 +1057,7 @@ namespace ts {
1057
1057
errors . push ( createDiagnosticForNodeInSourceFile ( sourceFile , element . name , extraKeyDiagnosticMessage , keyText ) ) ;
1058
1058
}
1059
1059
const value = convertPropertyValueToJson ( element . initializer , option ) ;
1060
- if ( typeof keyText !== "undefined" && typeof value !== "undefined" ) {
1060
+ if ( typeof keyText !== "undefined" ) {
1061
1061
result [ keyText ] = value ;
1062
1062
// Notify key value set, if user asked for it
1063
1063
if ( jsonConversionNotifier &&
@@ -1104,7 +1104,7 @@ namespace ts {
1104
1104
return false ;
1105
1105
1106
1106
case SyntaxKind . NullKeyword :
1107
- reportInvalidOptionValue ( ! ! option ) ;
1107
+ reportInvalidOptionValue ( option && option . name === "extends" ) ; // "extends" is the only option we don't allow null/undefined for
1108
1108
return null ; // tslint:disable-line:no-null-keyword
1109
1109
1110
1110
case SyntaxKind . StringLiteral :
@@ -1189,6 +1189,7 @@ namespace ts {
1189
1189
1190
1190
function isCompilerOptionsValue ( option : CommandLineOption , value : any ) : value is CompilerOptionsValue {
1191
1191
if ( option ) {
1192
+ if ( isNullOrUndefined ( value ) ) return true ; // All options are undefinable/nullable
1192
1193
if ( option . type === "list" ) {
1193
1194
return isArray ( value ) ;
1194
1195
}
@@ -1379,6 +1380,11 @@ namespace ts {
1379
1380
}
1380
1381
}
1381
1382
1383
+ function isNullOrUndefined ( x : any ) : x is null | undefined {
1384
+ // tslint:disable-next-line:no-null-keyword
1385
+ return x === undefined || x === null ;
1386
+ }
1387
+
1382
1388
/**
1383
1389
* Parse the contents of a config file from json or json source file (tsconfig.json).
1384
1390
* @param json The contents of the config file to parse
@@ -1419,7 +1425,7 @@ namespace ts {
1419
1425
1420
1426
function getFileNames ( ) : ExpandResult {
1421
1427
let fileNames : ReadonlyArray < string > ;
1422
- if ( hasProperty ( raw , "files" ) ) {
1428
+ if ( hasProperty ( raw , "files" ) && ! isNullOrUndefined ( raw [ "files" ] ) ) {
1423
1429
if ( isArray ( raw [ "files" ] ) ) {
1424
1430
fileNames = < ReadonlyArray < string > > raw [ "files" ] ;
1425
1431
if ( fileNames . length === 0 ) {
@@ -1432,7 +1438,7 @@ namespace ts {
1432
1438
}
1433
1439
1434
1440
let includeSpecs : ReadonlyArray < string > ;
1435
- if ( hasProperty ( raw , "include" ) ) {
1441
+ if ( hasProperty ( raw , "include" ) && ! isNullOrUndefined ( raw [ "include" ] ) ) {
1436
1442
if ( isArray ( raw [ "include" ] ) ) {
1437
1443
includeSpecs = < ReadonlyArray < string > > raw [ "include" ] ;
1438
1444
}
@@ -1442,7 +1448,7 @@ namespace ts {
1442
1448
}
1443
1449
1444
1450
let excludeSpecs : ReadonlyArray < string > ;
1445
- if ( hasProperty ( raw , "exclude" ) ) {
1451
+ if ( hasProperty ( raw , "exclude" ) && ! isNullOrUndefined ( raw [ "exclude" ] ) ) {
1446
1452
if ( isArray ( raw [ "exclude" ] ) ) {
1447
1453
excludeSpecs = < ReadonlyArray < string > > raw [ "exclude" ] ;
1448
1454
}
@@ -1461,7 +1467,7 @@ namespace ts {
1461
1467
includeSpecs = [ "**/*" ] ;
1462
1468
}
1463
1469
1464
- const result = matchFileNames ( fileNames , includeSpecs , excludeSpecs , basePath , options , host , errors , extraFileExtensions , sourceFile ) ;
1470
+ const result = matchFileNames ( fileNames , includeSpecs , excludeSpecs , configFileName ? getDirectoryPath ( toPath ( configFileName , basePath , createGetCanonicalFileName ( host . useCaseSensitiveFileNames ) ) ) : basePath , options , host , errors , extraFileExtensions , sourceFile ) ;
1465
1471
1466
1472
if ( result . fileNames . length === 0 && ! hasProperty ( raw , "files" ) && resolutionStack . length === 0 ) {
1467
1473
errors . push (
@@ -1552,7 +1558,7 @@ namespace ts {
1552
1558
host : ParseConfigHost ,
1553
1559
basePath : string ,
1554
1560
getCanonicalFileName : ( fileName : string ) => string ,
1555
- configFileName : string ,
1561
+ configFileName : string | undefined ,
1556
1562
errors : Push < Diagnostic >
1557
1563
) : ParsedTsconfig {
1558
1564
if ( hasProperty ( json , "excludes" ) ) {
@@ -1571,7 +1577,8 @@ namespace ts {
1571
1577
errors . push ( createCompilerDiagnostic ( Diagnostics . Compiler_option_0_requires_a_value_of_type_1 , "extends" , "string" ) ) ;
1572
1578
}
1573
1579
else {
1574
- extendedConfigPath = getExtendsConfigPath ( json . extends , host , basePath , getCanonicalFileName , errors , createCompilerDiagnostic ) ;
1580
+ const newBase = configFileName ? getDirectoryPath ( toPath ( configFileName , basePath , getCanonicalFileName ) ) : basePath ;
1581
+ extendedConfigPath = getExtendsConfigPath ( json . extends , host , newBase , getCanonicalFileName , errors , createCompilerDiagnostic ) ;
1575
1582
}
1576
1583
}
1577
1584
return { raw : json , options, typeAcquisition, extendedConfigPath } ;
@@ -1582,7 +1589,7 @@ namespace ts {
1582
1589
host : ParseConfigHost ,
1583
1590
basePath : string ,
1584
1591
getCanonicalFileName : ( fileName : string ) => string ,
1585
- configFileName : string ,
1592
+ configFileName : string | undefined ,
1586
1593
errors : Push < Diagnostic >
1587
1594
) : ParsedTsconfig {
1588
1595
const options = getDefaultCompilerOptions ( configFileName ) ;
@@ -1603,10 +1610,11 @@ namespace ts {
1603
1610
onSetValidOptionKeyValueInRoot ( key : string , _keyNode : PropertyName , value : CompilerOptionsValue , valueNode : Expression ) {
1604
1611
switch ( key ) {
1605
1612
case "extends" :
1613
+ const newBase = configFileName ? getDirectoryPath ( toPath ( configFileName , basePath , getCanonicalFileName ) ) : basePath ;
1606
1614
extendedConfigPath = getExtendsConfigPath (
1607
1615
< string > value ,
1608
1616
host ,
1609
- basePath ,
1617
+ newBase ,
1610
1618
getCanonicalFileName ,
1611
1619
errors ,
1612
1620
( message , arg0 ) =>
@@ -1803,6 +1811,7 @@ namespace ts {
1803
1811
}
1804
1812
1805
1813
function normalizeOptionValue ( option : CommandLineOption , basePath : string , value : any ) : CompilerOptionsValue {
1814
+ if ( isNullOrUndefined ( value ) ) return undefined ;
1806
1815
if ( option . type === "list" ) {
1807
1816
const listOption = < CommandLineOptionOfListType > option ;
1808
1817
if ( listOption . element . isFilePath || typeof listOption . element . type !== "string" ) {
@@ -1827,6 +1836,7 @@ namespace ts {
1827
1836
}
1828
1837
1829
1838
function convertJsonOptionOfCustomType ( opt : CommandLineOptionOfCustomType , value : string , errors : Push < Diagnostic > ) {
1839
+ if ( isNullOrUndefined ( value ) ) return undefined ;
1830
1840
const key = value . toLowerCase ( ) ;
1831
1841
const val = opt . type . get ( key ) ;
1832
1842
if ( val !== undefined ) {
@@ -1977,7 +1987,7 @@ namespace ts {
1977
1987
// remove a literal file.
1978
1988
if ( fileNames ) {
1979
1989
for ( const fileName of fileNames ) {
1980
- const file = combinePaths ( basePath , fileName ) ;
1990
+ const file = getNormalizedAbsolutePath ( fileName , basePath ) ;
1981
1991
literalFileMap . set ( keyMapper ( file ) , file ) ;
1982
1992
}
1983
1993
}
0 commit comments