diff --git a/internal/tsoptions/commandlineparser.go b/internal/tsoptions/commandlineparser.go index bc229a46536..3e537b2898e 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,11 @@ func getInputOptionName(input string) string { } func (p *commandLineParser) parseResponseFile(fileName string) { + if fileName == "" { + p.errors = append(p.errors, ast.NewCompilerDiagnostic(diagnostics.Cannot_read_file_0, fileName)) + return + } + fileName = tspath.CombinePaths(p.currentDirectory, fileName) 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..d0bc518ef11 100644 --- a/internal/tsoptions/commandlineparser_test.go +++ b/internal/tsoptions/commandlineparser_test.go @@ -87,6 +87,24 @@ func TestCommandLineParseResult(t *testing.T) { } } +func TestParseCommandLineEmptyResponseFile(t *testing.T) { + t.Parallel() + + host := tsoptionstest.NewVFSParseConfigHost(map[string]string{}, "/home/project", true) + cmdLine := tsoptions.ParseCommandLine([]string{"@"}, host) + + assert.Assert(t, len(cmdLine.Errors) > 0, "expected a diagnostic error for bare '@' argument") +} + +func TestParseCommandLineRelativeResponseFile(t *testing.T) { + t.Parallel() + + host := tsoptionstest.NewVFSParseConfigHost(map[string]string{}, "/home/project", true) + cmdLine := tsoptions.ParseCommandLine([]string{"@options.rsp"}, host) + + assert.Assert(t, len(cmdLine.Errors) > 0, "expected a diagnostic error for missing response file") +} + func TestParseCommandLineTypeRootsRelativePath(t *testing.T) { t.Parallel()