@@ -1087,12 +1087,15 @@ namespace ts {
1087
1087
[ option : string ] : CompilerOptionsValue | undefined ;
1088
1088
}
1089
1089
1090
- /** Tuple with error messages for 'unknown compiler option', 'option requires type' */
1091
- type ParseCommandLineWorkerDiagnostics = [ DiagnosticMessage , DiagnosticMessage ] ;
1090
+ interface ParseCommandLineWorkerDiagnostics {
1091
+ unknownOptionDiagnostic : DiagnosticMessage ,
1092
+ unknownDidYouMeanDiagnostic : DiagnosticMessage ,
1093
+ optionTypeMismatchDiagnostic : DiagnosticMessage
1094
+ }
1092
1095
1093
1096
function parseCommandLineWorker (
1094
1097
getOptionNameMap : ( ) => OptionNameMap ,
1095
- [ unknownOptionDiagnostic , optionTypeMismatchDiagnostic ] : ParseCommandLineWorkerDiagnostics ,
1098
+ diagnostics : ParseCommandLineWorkerDiagnostics ,
1096
1099
commandLine : readonly string [ ] ,
1097
1100
readFile ?: ( path : string ) => string | undefined ) {
1098
1101
const options = { } as OptionsBase ;
@@ -1123,7 +1126,7 @@ namespace ts {
1123
1126
else {
1124
1127
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
1125
1128
if ( ! args [ i ] && opt . type !== "boolean" ) {
1126
- errors . push ( createCompilerDiagnostic ( optionTypeMismatchDiagnostic , opt . name ) ) ;
1129
+ errors . push ( createCompilerDiagnostic ( diagnostics . optionTypeMismatchDiagnostic , opt . name ) ) ;
1127
1130
}
1128
1131
1129
1132
switch ( opt . type ) {
@@ -1160,7 +1163,13 @@ namespace ts {
1160
1163
}
1161
1164
}
1162
1165
else {
1163
- errors . push ( createCompilerDiagnostic ( unknownOptionDiagnostic , s ) ) ;
1166
+ const possibleOption = getSpellingSuggestion ( s , optionDeclarations , opt => `--${ opt . name } ` ) ;
1167
+ if ( possibleOption ) {
1168
+ errors . push ( createCompilerDiagnostic ( diagnostics . unknownDidYouMeanDiagnostic , s , possibleOption . name ) ) ;
1169
+ }
1170
+ else {
1171
+ errors . push ( createCompilerDiagnostic ( diagnostics . unknownOptionDiagnostic , s ) ) ;
1172
+ }
1164
1173
}
1165
1174
}
1166
1175
else {
@@ -1203,11 +1212,13 @@ namespace ts {
1203
1212
}
1204
1213
}
1205
1214
1215
+ const compilerOptionsDefaultDiagnostics = {
1216
+ unknownOptionDiagnostic : Diagnostics . Unknown_compiler_option_0 ,
1217
+ unknownDidYouMeanDiagnostic : Diagnostics . Unknown_compiler_option_0_Did_you_mean_1 ,
1218
+ optionTypeMismatchDiagnostic : Diagnostics . Compiler_option_0_expects_an_argument
1219
+ } ;
1206
1220
export function parseCommandLine ( commandLine : readonly string [ ] , readFile ?: ( path : string ) => string | undefined ) : ParsedCommandLine {
1207
- return parseCommandLineWorker ( getOptionNameMap , [
1208
- Diagnostics . Unknown_compiler_option_0 ,
1209
- Diagnostics . Compiler_option_0_expects_an_argument
1210
- ] , commandLine , readFile ) ;
1221
+ return parseCommandLineWorker ( getOptionNameMap , compilerOptionsDefaultDiagnostics , commandLine , readFile ) ;
1211
1222
}
1212
1223
1213
1224
/** @internal */
@@ -1239,10 +1250,11 @@ namespace ts {
1239
1250
export function parseBuildCommand ( args : readonly string [ ] ) : ParsedBuildCommand {
1240
1251
let buildOptionNameMap : OptionNameMap | undefined ;
1241
1252
const returnBuildOptionNameMap = ( ) => ( buildOptionNameMap || ( buildOptionNameMap = createOptionNameMap ( buildOpts ) ) ) ;
1242
- const { options, fileNames : projects , errors } = parseCommandLineWorker ( returnBuildOptionNameMap , [
1243
- Diagnostics . Unknown_build_option_0 ,
1244
- Diagnostics . Build_option_0_requires_a_value_of_type_1
1245
- ] , args ) ;
1253
+ const { options, fileNames : projects , errors } = parseCommandLineWorker ( returnBuildOptionNameMap , {
1254
+ unknownOptionDiagnostic : Diagnostics . Unknown_build_option_0 ,
1255
+ unknownDidYouMeanDiagnostic : Diagnostics . Unknown_build_option_0_Did_you_mean_1 ,
1256
+ optionTypeMismatchDiagnostic : Diagnostics . Build_option_0_requires_a_value_of_type_1
1257
+ } , args ) ;
1246
1258
const buildOptions = options as BuildOptions ;
1247
1259
1248
1260
if ( projects . length === 0 ) {
@@ -1389,19 +1401,28 @@ namespace ts {
1389
1401
name : "compilerOptions" ,
1390
1402
type : "object" ,
1391
1403
elementOptions : commandLineOptionsToMap ( optionDeclarations ) ,
1392
- extraKeyDiagnosticMessage : Diagnostics . Unknown_compiler_option_0
1404
+ extraKeyDiagnostics : {
1405
+ unknownOptionDiagnostic : Diagnostics . Unknown_compiler_option_0 ,
1406
+ unknownDidYouMeanDiagnostic : Diagnostics . Unknown_compiler_option_0_Did_you_mean_1
1407
+ } ,
1393
1408
} ,
1394
1409
{
1395
1410
name : "typingOptions" ,
1396
1411
type : "object" ,
1397
1412
elementOptions : commandLineOptionsToMap ( typeAcquisitionDeclarations ) ,
1398
- extraKeyDiagnosticMessage : Diagnostics . Unknown_type_acquisition_option_0
1413
+ extraKeyDiagnostics : {
1414
+ unknownOptionDiagnostic : Diagnostics . Unknown_type_acquisition_option_0 ,
1415
+ unknownDidYouMeanDiagnostic : Diagnostics . Unknown_type_acquisition_option_0_Did_you_mean_1
1416
+ } ,
1399
1417
} ,
1400
1418
{
1401
1419
name : "typeAcquisition" ,
1402
1420
type : "object" ,
1403
1421
elementOptions : commandLineOptionsToMap ( typeAcquisitionDeclarations ) ,
1404
- extraKeyDiagnosticMessage : Diagnostics . Unknown_type_acquisition_option_0
1422
+ extraKeyDiagnostics : {
1423
+ unknownOptionDiagnostic : Diagnostics . Unknown_type_acquisition_option_0 ,
1424
+ unknownDidYouMeanDiagnostic : Diagnostics . Unknown_type_acquisition_option_0_Did_you_mean_1
1425
+ }
1405
1426
} ,
1406
1427
{
1407
1428
name : "extends" ,
@@ -1507,7 +1528,7 @@ namespace ts {
1507
1528
function convertObjectLiteralExpressionToJson (
1508
1529
node : ObjectLiteralExpression ,
1509
1530
knownOptions : Map < CommandLineOption > | undefined ,
1510
- extraKeyDiagnosticMessage : DiagnosticMessage | undefined ,
1531
+ extraKeyDiagnostics : DidYouMeanOptionalDiagnostics | undefined ,
1511
1532
parentOption : string | undefined
1512
1533
) : any {
1513
1534
const result : any = returnValue ? { } : undefined ;
@@ -1527,8 +1548,19 @@ namespace ts {
1527
1548
const textOfKey = getTextOfPropertyName ( element . name ) ;
1528
1549
const keyText = textOfKey && unescapeLeadingUnderscores ( textOfKey ) ;
1529
1550
const option = keyText && knownOptions ? knownOptions . get ( keyText ) : undefined ;
1530
- if ( keyText && extraKeyDiagnosticMessage && ! option ) {
1531
- errors . push ( createDiagnosticForNodeInSourceFile ( sourceFile , element . name , extraKeyDiagnosticMessage , keyText ) ) ;
1551
+ if ( keyText && extraKeyDiagnostics && ! option ) {
1552
+ if ( knownOptions ) {
1553
+ const possibleOption = getSpellingSuggestion ( keyText , arrayFrom ( knownOptions . keys ( ) ) , identity ) ;
1554
+ if ( possibleOption ) {
1555
+ errors . push ( createDiagnosticForNodeInSourceFile ( sourceFile , element . name , extraKeyDiagnostics . unknownDidYouMeanDiagnostic , keyText , possibleOption ) ) ;
1556
+ }
1557
+ else {
1558
+ errors . push ( createDiagnosticForNodeInSourceFile ( sourceFile , element . name , extraKeyDiagnostics . unknownOptionDiagnostic , keyText ) ) ;
1559
+ }
1560
+ }
1561
+ else {
1562
+ errors . push ( createDiagnosticForNodeInSourceFile ( sourceFile , element . name , extraKeyDiagnostics . unknownOptionDiagnostic , keyText ) ) ;
1563
+ }
1532
1564
}
1533
1565
const value = convertPropertyValueToJson ( element . initializer , option ) ;
1534
1566
if ( typeof keyText !== "undefined" ) {
@@ -1630,9 +1662,9 @@ namespace ts {
1630
1662
// vs what we set in the json
1631
1663
// If need arises, we can modify this interface and callbacks as needed
1632
1664
if ( option ) {
1633
- const { elementOptions, extraKeyDiagnosticMessage , name : optionName } = < TsConfigOnlyOption > option ;
1665
+ const { elementOptions, extraKeyDiagnostics , name : optionName } = < TsConfigOnlyOption > option ;
1634
1666
return convertObjectLiteralExpressionToJson ( objectLiteralExpression ,
1635
- elementOptions , extraKeyDiagnosticMessage , optionName ) ;
1667
+ elementOptions , extraKeyDiagnostics , optionName ) ;
1636
1668
}
1637
1669
else {
1638
1670
return convertObjectLiteralExpressionToJson (
@@ -2468,7 +2500,7 @@ namespace ts {
2468
2500
basePath : string , errors : Push < Diagnostic > , configFileName ?: string ) : CompilerOptions {
2469
2501
2470
2502
const options = getDefaultCompilerOptions ( configFileName ) ;
2471
- convertOptionsFromJson ( optionDeclarations , jsonOptions , basePath , options , Diagnostics . Unknown_compiler_option_0 , errors ) ;
2503
+ convertOptionsFromJson ( optionDeclarations , jsonOptions , basePath , options , compilerOptionsDefaultDiagnostics , errors ) ;
2472
2504
if ( configFileName ) {
2473
2505
options . configFilePath = normalizeSlashes ( configFileName ) ;
2474
2506
}
@@ -2484,13 +2516,19 @@ namespace ts {
2484
2516
2485
2517
const options = getDefaultTypeAcquisition ( configFileName ) ;
2486
2518
const typeAcquisition = convertEnableAutoDiscoveryToEnable ( jsonOptions ) ;
2487
- convertOptionsFromJson ( typeAcquisitionDeclarations , typeAcquisition , basePath , options , Diagnostics . Unknown_type_acquisition_option_0 , errors ) ;
2519
+
2520
+ const diagnostics = {
2521
+ unknownOptionDiagnostic : Diagnostics . Unknown_type_acquisition_option_0 ,
2522
+ unknownDidYouMeanDiagnostic : Diagnostics . Unknown_type_acquisition_option_0_Did_you_mean_1 ,
2523
+ } ;
2524
+ convertOptionsFromJson ( typeAcquisitionDeclarations , typeAcquisition , basePath , options , diagnostics , errors ) ;
2488
2525
2489
2526
return options ;
2490
2527
}
2491
2528
2529
+
2492
2530
function convertOptionsFromJson ( optionDeclarations : readonly CommandLineOption [ ] , jsonOptions : any , basePath : string ,
2493
- defaultOptions : CompilerOptions | TypeAcquisition , diagnosticMessage : DiagnosticMessage , errors : Push < Diagnostic > ) {
2531
+ defaultOptions : CompilerOptions | TypeAcquisition , diagnostics : DidYouMeanOptionalDiagnostics , errors : Push < Diagnostic > ) {
2494
2532
2495
2533
if ( ! jsonOptions ) {
2496
2534
return ;
@@ -2504,7 +2542,13 @@ namespace ts {
2504
2542
defaultOptions [ opt . name ] = convertJsonOption ( opt , jsonOptions [ id ] , basePath , errors ) ;
2505
2543
}
2506
2544
else {
2507
- errors . push ( createCompilerDiagnostic ( diagnosticMessage , id ) ) ;
2545
+ const possibleOption = getSpellingSuggestion ( id , < CommandLineOption [ ] > optionDeclarations , opt => opt . name ) ;
2546
+ if ( possibleOption ) {
2547
+ errors . push ( createCompilerDiagnostic ( diagnostics . unknownDidYouMeanDiagnostic , id , possibleOption . name ) ) ;
2548
+ }
2549
+ else {
2550
+ errors . push ( createCompilerDiagnostic ( diagnostics . unknownOptionDiagnostic , id ) ) ;
2551
+ }
2508
2552
}
2509
2553
}
2510
2554
}
0 commit comments