@@ -1087,12 +1087,15 @@ namespace ts {
10871087 [ option : string ] : CompilerOptionsValue | undefined ;
10881088 }
10891089
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+ }
10921095
10931096 function parseCommandLineWorker (
10941097 getOptionNameMap : ( ) => OptionNameMap ,
1095- [ unknownOptionDiagnostic , optionTypeMismatchDiagnostic ] : ParseCommandLineWorkerDiagnostics ,
1098+ diagnostics : ParseCommandLineWorkerDiagnostics ,
10961099 commandLine : readonly string [ ] ,
10971100 readFile ?: ( path : string ) => string | undefined ) {
10981101 const options = { } as OptionsBase ;
@@ -1123,7 +1126,7 @@ namespace ts {
11231126 else {
11241127 // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
11251128 if ( ! args [ i ] && opt . type !== "boolean" ) {
1126- errors . push ( createCompilerDiagnostic ( optionTypeMismatchDiagnostic , opt . name ) ) ;
1129+ errors . push ( createCompilerDiagnostic ( diagnostics . optionTypeMismatchDiagnostic , opt . name ) ) ;
11271130 }
11281131
11291132 switch ( opt . type ) {
@@ -1160,7 +1163,13 @@ namespace ts {
11601163 }
11611164 }
11621165 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+ }
11641173 }
11651174 }
11661175 else {
@@ -1203,11 +1212,13 @@ namespace ts {
12031212 }
12041213 }
12051214
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+ } ;
12061220 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 ) ;
12111222 }
12121223
12131224 /** @internal */
@@ -1239,10 +1250,11 @@ namespace ts {
12391250 export function parseBuildCommand ( args : readonly string [ ] ) : ParsedBuildCommand {
12401251 let buildOptionNameMap : OptionNameMap | undefined ;
12411252 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 ) ;
12461258 const buildOptions = options as BuildOptions ;
12471259
12481260 if ( projects . length === 0 ) {
@@ -1389,19 +1401,28 @@ namespace ts {
13891401 name : "compilerOptions" ,
13901402 type : "object" ,
13911403 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+ } ,
13931408 } ,
13941409 {
13951410 name : "typingOptions" ,
13961411 type : "object" ,
13971412 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+ } ,
13991417 } ,
14001418 {
14011419 name : "typeAcquisition" ,
14021420 type : "object" ,
14031421 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+ }
14051426 } ,
14061427 {
14071428 name : "extends" ,
@@ -1507,7 +1528,7 @@ namespace ts {
15071528 function convertObjectLiteralExpressionToJson (
15081529 node : ObjectLiteralExpression ,
15091530 knownOptions : Map < CommandLineOption > | undefined ,
1510- extraKeyDiagnosticMessage : DiagnosticMessage | undefined ,
1531+ extraKeyDiagnostics : DidYouMeanOptionalDiagnostics | undefined ,
15111532 parentOption : string | undefined
15121533 ) : any {
15131534 const result : any = returnValue ? { } : undefined ;
@@ -1527,8 +1548,19 @@ namespace ts {
15271548 const textOfKey = getTextOfPropertyName ( element . name ) ;
15281549 const keyText = textOfKey && unescapeLeadingUnderscores ( textOfKey ) ;
15291550 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+ }
15321564 }
15331565 const value = convertPropertyValueToJson ( element . initializer , option ) ;
15341566 if ( typeof keyText !== "undefined" ) {
@@ -1630,9 +1662,9 @@ namespace ts {
16301662 // vs what we set in the json
16311663 // If need arises, we can modify this interface and callbacks as needed
16321664 if ( option ) {
1633- const { elementOptions, extraKeyDiagnosticMessage , name : optionName } = < TsConfigOnlyOption > option ;
1665+ const { elementOptions, extraKeyDiagnostics , name : optionName } = < TsConfigOnlyOption > option ;
16341666 return convertObjectLiteralExpressionToJson ( objectLiteralExpression ,
1635- elementOptions , extraKeyDiagnosticMessage , optionName ) ;
1667+ elementOptions , extraKeyDiagnostics , optionName ) ;
16361668 }
16371669 else {
16381670 return convertObjectLiteralExpressionToJson (
@@ -2468,7 +2500,7 @@ namespace ts {
24682500 basePath : string , errors : Push < Diagnostic > , configFileName ?: string ) : CompilerOptions {
24692501
24702502 const options = getDefaultCompilerOptions ( configFileName ) ;
2471- convertOptionsFromJson ( optionDeclarations , jsonOptions , basePath , options , Diagnostics . Unknown_compiler_option_0 , errors ) ;
2503+ convertOptionsFromJson ( optionDeclarations , jsonOptions , basePath , options , compilerOptionsDefaultDiagnostics , errors ) ;
24722504 if ( configFileName ) {
24732505 options . configFilePath = normalizeSlashes ( configFileName ) ;
24742506 }
@@ -2484,13 +2516,19 @@ namespace ts {
24842516
24852517 const options = getDefaultTypeAcquisition ( configFileName ) ;
24862518 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 ) ;
24882525
24892526 return options ;
24902527 }
24912528
2529+
24922530 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 > ) {
24942532
24952533 if ( ! jsonOptions ) {
24962534 return ;
@@ -2504,7 +2542,13 @@ namespace ts {
25042542 defaultOptions [ opt . name ] = convertJsonOption ( opt , jsonOptions [ id ] , basePath , errors ) ;
25052543 }
25062544 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+ }
25082552 }
25092553 }
25102554 }
0 commit comments