@@ -15,6 +15,8 @@ import (
1515 "github.com/microsoft/typescript-go/internal/testutil/baseline"
1616 "github.com/microsoft/typescript-go/internal/testutil/filefixture"
1717 "github.com/microsoft/typescript-go/internal/tsoptions"
18+ "github.com/microsoft/typescript-go/internal/tsoptions/tsoptionstest"
19+ "github.com/microsoft/typescript-go/internal/tspath"
1820 "github.com/microsoft/typescript-go/internal/vfs/osvfs"
1921 "gotest.tools/v3/assert"
2022)
@@ -80,7 +82,7 @@ func TestCommandLineParseResult(t *testing.T) {
8082 }
8183
8284 for _ , testCase := range parseCommandLineSubScenarios {
83- testCase .createSubScenario ().assertParseResult (t )
85+ testCase .createSubScenario ("parseCommandLine" ).assertParseResult (t )
8486 }
8587}
8688
@@ -89,7 +91,7 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
8991 repo .SkipIfNoTypeScriptSubmodule (t )
9092
9193 // run test for boolean
92- subScenarioInput {"allows setting option type boolean to false" , []string {"--composite" , "false" , "0.ts" }}.createSubScenario ().assertParseResult (t )
94+ subScenarioInput {"allows setting option type boolean to false" , []string {"--composite" , "false" , "0.ts" }}.createSubScenario ("parseCommandLine" ).assertParseResult (t )
9395
9496 verifyNullSubScenarios := []verifyNull {
9597 {
@@ -114,26 +116,30 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
114116
115117 for _ , verifyNullCase := range verifyNullSubScenarios {
116118 createSubScenario (
119+ "parseCommandLine" ,
117120 verifyNullCase .subScenario + " allows setting it to null" ,
118121 []string {"--" + verifyNullCase .optionName , "null" , "0.ts" },
119122 verifyNullCase .optDecls ,
120123 ).assertParseResult (t )
121124
122125 if verifyNullCase .nonNullValue != "" {
123126 createSubScenario (
127+ "parseCommandLine" ,
124128 verifyNullCase .subScenario + " errors if non null value is passed" ,
125129 []string {"--" + verifyNullCase .optionName , verifyNullCase .nonNullValue , "0.ts" },
126130 verifyNullCase .optDecls ,
127131 ).assertParseResult (t )
128132 }
129133
130134 createSubScenario (
135+ "parseCommandLine" ,
131136 verifyNullCase .subScenario + " errors if its followed by another option" ,
132137 []string {"0.ts" , "--strictNullChecks" , "--" + verifyNullCase .optionName },
133138 verifyNullCase .optDecls ,
134139 ).assertParseResult (t )
135140
136141 createSubScenario (
142+ "parseCommandLine" ,
137143 verifyNullCase .subScenario + " errors if its last option" ,
138144 []string {"0.ts" , "--" + verifyNullCase .optionName },
139145 verifyNullCase .optDecls ,
@@ -195,10 +201,6 @@ func (f commandLineSubScenario) assertParseResult(t *testing.T) {
195201 })
196202}
197203
198- func (f * commandLineSubScenario ) getBaselineName () (baseline.Options , string ) {
199- return baseline.Options {Subfolder : "tsoptions/commandLineParsing" }, f .testName
200- }
201-
202204func parseExistingCompilerBaseline (t * testing.T , baseline string ) * TestCommandLineParser {
203205 _ , rest , _ := strings .Cut (baseline , "CompilerOptions::\n " )
204206 compilerOptions , rest , watchFound := strings .Cut (rest , "\n WatchOptions::\n " )
@@ -243,27 +245,112 @@ func formatNewBaseline(
243245 return formatted .String ()
244246}
245247
246- // todo: --build not implemented
247- // func parseExistingBuildBaseline(baseline string) *TestCommandLineParser {
248- // _, rest, _ := strings.Cut(baseline, "BuildOptions::\n")
249- // buildOptions, rest, _ := strings.Cut(rest, "\nWatchOptions::\n")
250- // _, rest, _ = strings.Cut(rest, "\nProjects::\n")
251- // fileNames, errors, _ := strings.Cut(rest, "\nErrors::\n")
248+ func (f commandLineSubScenario ) assertBuildParseResult (t * testing.T ) {
249+ t .Helper ()
250+ t .Run (f .testName , func (t * testing.T ) {
251+ t .Parallel ()
252+ originalBaseline := f .baseline .ReadFile (t )
253+ tsBaseline := parseExistingCompilerBaselineBuild (t , originalBaseline )
254+
255+ // f.workerDiagnostic is either defined or set to default pointer in `createSubScenario`
256+ parsed := tsoptions .ParseBuildCommandLine (f .commandLine , & tsoptionstest.VfsParseConfigHost {
257+ Vfs : osvfs .FS (),
258+ CurrentDirectory : tspath .NormalizeSlashes (repo .TypeScriptSubmodulePath ),
259+ })
260+
261+ newBaselineProjects := strings .Join (parsed .Projects , "," )
262+ assert .Equal (t , tsBaseline .projects , newBaselineProjects )
263+
264+ o , _ := json .Marshal (parsed .BuildOptions )
265+ newParsedBuildOptions := & core.BuildOptions {}
266+ e := json .Unmarshal (o , newParsedBuildOptions )
267+ assert .NilError (t , e )
268+ assert .DeepEqual (t , tsBaseline .options , newParsedBuildOptions , cmpopts .IgnoreUnexported (core.BuildOptions {}))
269+
270+ compilerOpts , _ := json .Marshal (parsed .CompilerOptions )
271+ newParsedCompilerOptions := & core.CompilerOptions {}
272+ e = json .Unmarshal (compilerOpts , newParsedCompilerOptions )
273+ assert .NilError (t , e )
274+ assert .DeepEqual (t , tsBaseline .compilerOptions , newParsedCompilerOptions , cmpopts .IgnoreUnexported (core.CompilerOptions {}))
275+
276+ newParsedWatchOptions := core.WatchOptions {}
277+ e = json .Unmarshal (o , & newParsedWatchOptions )
278+ assert .NilError (t , e )
279+
280+ // !!! useful for debugging but will not pass due to `none` as enum options
281+ // assert.DeepEqual(t, tsBaseline.watchoptions, newParsedWatchOptions)
282+
283+ var formattedErrors strings.Builder
284+ diagnosticwriter .WriteFormatDiagnostics (& formattedErrors , parsed .Errors , & diagnosticwriter.FormattingOptions {NewLine : "\n " })
285+ newBaselineErrors := formattedErrors .String ()
286+
287+ // !!!
288+ // useful for debugging--compares the new errors with the old errors. currently will NOT pass because of unimplemented options, not completely identical enum options, etc
289+ // assert.Equal(t, tsBaseline.errors, newBaselineErrors)
290+
291+ baseline .Run (t , f .testName + ".js" , formatNewBaselineBuild (f .commandLine , o , compilerOpts , newBaselineProjects , newBaselineErrors ), baseline.Options {Subfolder : "tsoptions/commandLineParsing" })
292+ })
293+ }
294+
295+ func parseExistingCompilerBaselineBuild (t * testing.T , baseline string ) * TestCommandLineParserBuild {
296+ _ , rest , _ := strings .Cut (baseline , "buildOptions::\n " )
297+ buildOptions , rest , watchFound := strings .Cut (rest , "\n WatchOptions::\n " )
298+ watchOptions , rest , _ := strings .Cut (rest , "\n Projects::\n " )
299+ projects , errors , _ := strings .Cut (rest , "\n Errors::\n " )
300+
301+ baselineBuildOptions := & core.BuildOptions {}
302+ e := json .Unmarshal ([]byte (buildOptions ), & baselineBuildOptions )
303+ assert .NilError (t , e )
304+
305+ baselineCompilerOptions := & core.CompilerOptions {}
306+ e = json .Unmarshal ([]byte (buildOptions ), & baselineCompilerOptions )
307+ assert .NilError (t , e )
252308
253- // // todo: change CompilerOptions to buildoptions
254- // baselineOptions := &core.CompilerOptions{}
255- // json.Unmarshal([]byte(buildOptions), &baselineOptions)
309+ baselineWatchOptions := & core.WatchOptions {}
310+ if watchFound && watchOptions != "" {
311+ e2 := json .Unmarshal ([]byte (watchOptions ), & baselineWatchOptions )
312+ assert .NilError (t , e2 )
313+ }
314+
315+ return & TestCommandLineParserBuild {
316+ options : baselineBuildOptions ,
317+ compilerOptions : baselineCompilerOptions ,
318+ watchoptions : baselineWatchOptions ,
319+ projects : projects ,
320+ errors : errors ,
321+ }
322+ }
256323
257- // var parser = TestCommandLineParser{
258- // options: *baselineOptions,
259- // fileNames: fileNames,
260- // errors: errors,
261- // }
262- // return &parser
263- // }
324+ func formatNewBaselineBuild (
325+ commandLine []string ,
326+ opts []byte ,
327+ compilerOpts []byte ,
328+ projects string ,
329+ errors string ,
330+ ) string {
331+ var formatted strings.Builder
332+ formatted .WriteString ("Args::\n " )
333+ if len (commandLine ) == 0 {
334+ formatted .WriteString ("[]" )
335+ } else {
336+ formatted .WriteString ("[\" " + strings .Join (commandLine , "\" , \" " ) + "\" ]" )
337+ }
338+ formatted .WriteString ("\n \n buildOptions::\n " )
339+ formatted .Write (opts )
340+ formatted .WriteString ("\n \n compilerOptions::\n " )
341+ formatted .Write (compilerOpts )
342+ // todo: watch options not implemented
343+ // formatted.WriteString("WatchOptions::\n")
344+ formatted .WriteString ("\n \n Projects::\n " )
345+ formatted .WriteString (projects )
346+ formatted .WriteString ("\n \n Errors::\n " )
347+ formatted .WriteString (errors )
348+ return formatted .String ()
349+ }
264350
265- func createSubScenario (subScenarioName string , commandline []string , opts ... []* tsoptions.CommandLineOption ) * commandLineSubScenario {
266- baselineFileName := "tests/baselines/reference/config/commandLineParsing/parseCommandLine/" + subScenarioName + ".js"
351+ func createSubScenario (scenarioKind string , subScenarioName string , commandline []string , opts ... []* tsoptions.CommandLineOption ) * commandLineSubScenario {
352+ subScenarioName = scenarioKind + "/" + subScenarioName
353+ baselineFileName := "tests/baselines/reference/config/commandLineParsing/" + subScenarioName + ".js"
267354
268355 result := & commandLineSubScenario {
269356 filefixture .FromFile (subScenarioName , filepath .Join (repo .TypeScriptSubmodulePath , baselineFileName )),
@@ -282,8 +369,8 @@ type subScenarioInput struct {
282369 commandLineArgs []string
283370}
284371
285- func (f subScenarioInput ) createSubScenario () * commandLineSubScenario {
286- return createSubScenario (f .name , f .commandLineArgs )
372+ func (f subScenarioInput ) createSubScenario (scenarioKind string ) * commandLineSubScenario {
373+ return createSubScenario (scenarioKind , f .name , f .commandLineArgs )
287374}
288375
289376type commandLineSubScenario struct {
@@ -306,6 +393,47 @@ type TestCommandLineParser struct {
306393 fileNames , errors string
307394}
308395
396+ type TestCommandLineParserBuild struct {
397+ options * core.BuildOptions
398+ compilerOptions * core.CompilerOptions
399+ watchoptions * core.WatchOptions
400+ projects , errors string
401+ }
402+
403+ func TestParseBuildCommandLine (t * testing.T ) {
404+ t .Parallel ()
405+ repo .SkipIfNoTypeScriptSubmodule (t )
406+
407+ parseCommandLineSubScenarios := []* subScenarioInput {
408+ {"parse build without any options " , []string {}},
409+ {"Parse multiple options" , []string {"--verbose" , "--force" , "tests" }},
410+ {"Parse option with invalid option" , []string {"--verbose" , "--invalidOption" }},
411+ {"Parse multiple flags with input projects at the end" , []string {"--force" , "--verbose" , "src" , "tests" }},
412+ {"Parse multiple flags with input projects in the middle" , []string {"--force" , "src" , "tests" , "--verbose" }},
413+ {"Parse multiple flags with input projects in the beginning" , []string {"src" , "tests" , "--force" , "--verbose" }},
414+ {"parse build with --incremental" , []string {"--incremental" , "tests" }},
415+ {"parse build with --locale en-us" , []string {"--locale" , "en-us" , "src" }},
416+ {"parse build with --tsBuildInfoFile" , []string {"--tsBuildInfoFile" , "build.tsbuildinfo" , "tests" }},
417+ {"reports other common may not be used with --build flags" , []string {"--strict" }},
418+ {`--clean and --force together is invalid` , []string {"--clean" , "--force" }},
419+ {`--clean and --verbose together is invalid` , []string {"--clean" , "--verbose" }},
420+ {`--clean and --watch together is invalid` , []string {"--clean" , "--watch" }},
421+ {`--watch and --dry together is invalid` , []string {"--watch" , "--dry" }},
422+ {"parse --watchFile" , []string {"--watchFile" , "UseFsEvents" , "--verbose" }},
423+ {"parse --watchDirectory" , []string {"--watchDirectory" , "FixedPollingInterval" , "--verbose" }},
424+ {"parse --fallbackPolling" , []string {"--fallbackPolling" , "PriorityInterval" , "--verbose" }},
425+ {"parse --synchronousWatchDirectory" , []string {"--synchronousWatchDirectory" , "--verbose" }},
426+ {"errors on missing argument" , []string {"--verbose" , "--fallbackPolling" }},
427+ {"errors on invalid excludeDirectories" , []string {"--excludeDirectories" , "**/../*" }},
428+ {"parse --excludeFiles" , []string {"--excludeFiles" , "**/temp/*.ts" }},
429+ {"errors on invalid excludeFiles" , []string {"--excludeFiles" , "**/../*" }},
430+ }
431+
432+ for _ , testCase := range parseCommandLineSubScenarios {
433+ testCase .createSubScenario ("parseBuildOptions" ).assertBuildParseResult (t )
434+ }
435+ }
436+
309437func TestAffectsBuildInfo (t * testing.T ) {
310438 t .Parallel ()
311439 t .Run ("should have affectsBuildInfo true for every option with affectsSemanticDiagnostics" , func (t * testing.T ) {
0 commit comments