@@ -15,6 +15,8 @@ import (
15
15
"github.com/microsoft/typescript-go/internal/testutil/baseline"
16
16
"github.com/microsoft/typescript-go/internal/testutil/filefixture"
17
17
"github.com/microsoft/typescript-go/internal/tsoptions"
18
+ "github.com/microsoft/typescript-go/internal/tsoptions/tsoptionstest"
19
+ "github.com/microsoft/typescript-go/internal/tspath"
18
20
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
19
21
"gotest.tools/v3/assert"
20
22
)
@@ -80,7 +82,7 @@ func TestCommandLineParseResult(t *testing.T) {
80
82
}
81
83
82
84
for _ , testCase := range parseCommandLineSubScenarios {
83
- testCase .createSubScenario ().assertParseResult (t )
85
+ testCase .createSubScenario ("parseCommandLine" ).assertParseResult (t )
84
86
}
85
87
}
86
88
@@ -89,7 +91,7 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
89
91
repo .SkipIfNoTypeScriptSubmodule (t )
90
92
91
93
// 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 )
93
95
94
96
verifyNullSubScenarios := []verifyNull {
95
97
{
@@ -114,26 +116,30 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
114
116
115
117
for _ , verifyNullCase := range verifyNullSubScenarios {
116
118
createSubScenario (
119
+ "parseCommandLine" ,
117
120
verifyNullCase .subScenario + " allows setting it to null" ,
118
121
[]string {"--" + verifyNullCase .optionName , "null" , "0.ts" },
119
122
verifyNullCase .optDecls ,
120
123
).assertParseResult (t )
121
124
122
125
if verifyNullCase .nonNullValue != "" {
123
126
createSubScenario (
127
+ "parseCommandLine" ,
124
128
verifyNullCase .subScenario + " errors if non null value is passed" ,
125
129
[]string {"--" + verifyNullCase .optionName , verifyNullCase .nonNullValue , "0.ts" },
126
130
verifyNullCase .optDecls ,
127
131
).assertParseResult (t )
128
132
}
129
133
130
134
createSubScenario (
135
+ "parseCommandLine" ,
131
136
verifyNullCase .subScenario + " errors if its followed by another option" ,
132
137
[]string {"0.ts" , "--strictNullChecks" , "--" + verifyNullCase .optionName },
133
138
verifyNullCase .optDecls ,
134
139
).assertParseResult (t )
135
140
136
141
createSubScenario (
142
+ "parseCommandLine" ,
137
143
verifyNullCase .subScenario + " errors if its last option" ,
138
144
[]string {"0.ts" , "--" + verifyNullCase .optionName },
139
145
verifyNullCase .optDecls ,
@@ -195,10 +201,6 @@ func (f commandLineSubScenario) assertParseResult(t *testing.T) {
195
201
})
196
202
}
197
203
198
- func (f * commandLineSubScenario ) getBaselineName () (baseline.Options , string ) {
199
- return baseline.Options {Subfolder : "tsoptions/commandLineParsing" }, f .testName
200
- }
201
-
202
204
func parseExistingCompilerBaseline (t * testing.T , baseline string ) * TestCommandLineParser {
203
205
_ , rest , _ := strings .Cut (baseline , "CompilerOptions::\n " )
204
206
compilerOptions , rest , watchFound := strings .Cut (rest , "\n WatchOptions::\n " )
@@ -243,27 +245,112 @@ func formatNewBaseline(
243
245
return formatted .String ()
244
246
}
245
247
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 )
252
308
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
+ }
256
323
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
+ }
264
350
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"
267
354
268
355
result := & commandLineSubScenario {
269
356
filefixture .FromFile (subScenarioName , filepath .Join (repo .TypeScriptSubmodulePath , baselineFileName )),
@@ -282,8 +369,8 @@ type subScenarioInput struct {
282
369
commandLineArgs []string
283
370
}
284
371
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 )
287
374
}
288
375
289
376
type commandLineSubScenario struct {
@@ -306,6 +393,47 @@ type TestCommandLineParser struct {
306
393
fileNames , errors string
307
394
}
308
395
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
+
309
437
func TestAffectsBuildInfo (t * testing.T ) {
310
438
t .Parallel ()
311
439
t .Run ("should have affectsBuildInfo true for every option with affectsSemanticDiagnostics" , func (t * testing.T ) {
0 commit comments