diff --git a/internal/tsoptions/commandlineparser.go b/internal/tsoptions/commandlineparser.go index bc229a46536..1febf72fb97 100644 --- a/internal/tsoptions/commandlineparser.go +++ b/internal/tsoptions/commandlineparser.go @@ -33,6 +33,7 @@ type commandLineParser struct { workerDiagnostics *ParseCommandLineWorkerDiagnostics optionsMap *NameMap fs vfs.FS + currentDirectory string options *collections.OrderedMap[string, any] fileNames []string errors []*ast.Diagnostic @@ -45,7 +46,7 @@ func ParseCommandLine( if commandLine == nil { commandLine = []string{} } - parser := parseCommandLineWorker(CompilerOptionsDidYouMeanDiagnostics, commandLine, host.FS()) + parser := parseCommandLineWorker(CompilerOptionsDidYouMeanDiagnostics, commandLine, host.FS(), host.GetCurrentDirectory()) optionsWithAbsolutePaths := convertToOptionsWithAbsolutePaths(parser.options.Clone(), CommandLineCompilerOptionsMap, host.GetCurrentDirectory()) compilerOptions := convertMapToOptions(optionsWithAbsolutePaths, &compilerOptionsParser{&core.CompilerOptions{}}).CompilerOptions watchOptions := convertMapToOptions(optionsWithAbsolutePaths, &watchOptionsParser{&core.WatchOptions{}}).WatchOptions @@ -66,7 +67,7 @@ func ParseBuildCommandLine( if commandLine == nil { commandLine = []string{} } - parser := parseCommandLineWorker(buildOptionsDidYouMeanDiagnostics, commandLine, host.FS()) + parser := parseCommandLineWorker(buildOptionsDidYouMeanDiagnostics, commandLine, host.FS(), host.GetCurrentDirectory()) compilerOptions := &core.CompilerOptions{} for key, value := range parser.options.Entries() { buildOption := BuildNameMap.Get(key) @@ -114,9 +115,11 @@ func parseCommandLineWorker( parseCommandLineWithDiagnostics *ParseCommandLineWorkerDiagnostics, commandLine []string, fs vfs.FS, + currentDirectory string, ) *commandLineParser { parser := &commandLineParser{ fs: fs, + currentDirectory: currentDirectory, workerDiagnostics: parseCommandLineWithDiagnostics, fileNames: []string{}, options: &collections.OrderedMap[string, any]{}, @@ -163,6 +166,7 @@ func getInputOptionName(input string) string { } func (p *commandLineParser) parseResponseFile(fileName string) { + fileName = tspath.GetNormalizedAbsolutePath(fileName, p.currentDirectory) fileContents, errors := tryReadFile(fileName, func(fileName string) (string, bool) { if p.fs == nil { return "", false diff --git a/internal/tsoptions/commandlineparser_test.go b/internal/tsoptions/commandlineparser_test.go index dad9977012e..474329931f8 100644 --- a/internal/tsoptions/commandlineparser_test.go +++ b/internal/tsoptions/commandlineparser_test.go @@ -87,6 +87,25 @@ func TestCommandLineParseResult(t *testing.T) { } } +func TestResponseFileDoesNotPanic(t *testing.T) { + t.Parallel() + + // Passing `@` with an empty or relative filename should not panic. + // It should produce a diagnostic error instead. + cwd := t.TempDir() + t.Run("empty response file", func(t *testing.T) { + t.Parallel() + parsed := tsoptions.ParseCommandLineTestWorker(nil, []string{"@"}, osvfs.FS(), cwd) + assert.Assert(t, len(parsed.Errors) > 0, "expected an error for empty response file name") + }) + + t.Run("relative response file", func(t *testing.T) { + t.Parallel() + parsed := tsoptions.ParseCommandLineTestWorker(nil, []string{"@blah"}, osvfs.FS(), cwd) + assert.Assert(t, len(parsed.Errors) > 0, "expected an error for non-existent response file") + }) +} + func TestParseCommandLineTypeRootsRelativePath(t *testing.T) { t.Parallel() @@ -233,7 +252,7 @@ func (f commandLineSubScenario) assertParseResult(t *testing.T) { tsBaseline := parseExistingCompilerBaseline(t, originalBaseline) // f.workerDiagnostic is either defined or set to default pointer in `createSubScenario` - parsed := tsoptions.ParseCommandLineTestWorker(f.optDecls, f.commandLine, osvfs.FS()) + parsed := tsoptions.ParseCommandLineTestWorker(f.optDecls, f.commandLine, osvfs.FS(), t.TempDir()) newBaselineFileNames := strings.Join(parsed.FileNames, ",") assert.Equal(t, tsBaseline.fileNames, newBaselineFileNames) diff --git a/internal/tsoptions/export_test.go b/internal/tsoptions/export_test.go index bc5d78e6c7e..cbf10d2e0de 100644 --- a/internal/tsoptions/export_test.go +++ b/internal/tsoptions/export_test.go @@ -17,9 +17,11 @@ func ParseCommandLineTestWorker( decls []*CommandLineOption, commandLine []string, fs vfs.FS, + currentDirectory string, ) *TestCommandLineParser { parser := &commandLineParser{ fs: fs, + currentDirectory: currentDirectory, workerDiagnostics: CompilerOptionsDidYouMeanDiagnostics, fileNames: []string{}, options: &collections.OrderedMap[string, any]{},