From 5e910e916ad8a5ece84f7171dca0aeddeebf8ae0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:54:39 +0000 Subject: [PATCH 1/3] Initial plan From 9c460afb6225566ab34ba5eb7cf51cac28972ec2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:35:40 +0000 Subject: [PATCH 2/3] Fix malformed tsconfig diagnostics Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/execute/tsctests/tsc_test.go | 8 +++ internal/parser/parser.go | 2 +- internal/tsoptions/tsconfigparsing.go | 8 ++- ...lformed-tsconfig-property-without-value.js | 51 +++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 testdata/baselines/reference/tsc/commandLine/malformed-tsconfig-property-without-value.js diff --git a/internal/execute/tsctests/tsc_test.go b/internal/execute/tsctests/tsc_test.go index 29cba7ba4e2..00ed1838c9d 100644 --- a/internal/execute/tsctests/tsc_test.go +++ b/internal/execute/tsctests/tsc_test.go @@ -51,6 +51,14 @@ func TestTscCommandline(t *testing.T) { subScenario: "when build not first argument", commandLineArgs: []string{"--verbose", "--build"}, }, + { + subScenario: "malformed tsconfig property without value", + files: FileMap{ + "/home/src/workspaces/project/tsconfig.json": `{"" }`, + "/home/src/workspaces/project/index.ts": "", + }, + commandLineArgs: nil, + }, { subScenario: "Initialized TSConfig with files options", commandLineArgs: []string{"--init", "file0.st", "file1.ts", "file2.ts"}, diff --git a/internal/parser/parser.go b/internal/parser/parser.go index a8cd3a6f3d2..4a3e16a8dc3 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -228,7 +228,7 @@ func (p *Parser) parseJSONText() *ast.SourceFile { func getErrorSpanForNode(sourceText string, node *ast.Node) core.TextRange { pos := scanner.SkipTrivia(sourceText, node.Pos()) - return core.NewTextRange(pos, node.End()) + return core.NewTextRange(min(pos, node.End()), max(pos, node.End())) } func (p *Parser) validateJsonValue(sourceFile *ast.SourceFile, valueExpression *ast.Expression) { diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go index b1e1955b1f9..ae6bf8a6e96 100644 --- a/internal/tsoptions/tsconfigparsing.go +++ b/internal/tsoptions/tsconfigparsing.go @@ -261,7 +261,13 @@ func parseOwnConfigOfJsonSourceFile( onPropertySet, }, ) - errors = append(errors, err...) + for _, diagnostic := range err { + if !slices.ContainsFunc(sourceFile.Diagnostics(), func(parseDiagnostic *ast.Diagnostic) bool { + return parseDiagnostic.Code() == diagnostic.Code() && parseDiagnostic.Pos() == diagnostic.Pos() + }) { + errors = append(errors, diagnostic) + } + } // if len(rootCompilerOptions) != 0 && json != nil && json.CompilerOptions != nil { // errors = append(errors, ast.NewDiagnostic(sourceFile, rootCompilerOptions[0], diagnostics.X_0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file)) // } diff --git a/testdata/baselines/reference/tsc/commandLine/malformed-tsconfig-property-without-value.js b/testdata/baselines/reference/tsc/commandLine/malformed-tsconfig-property-without-value.js new file mode 100644 index 00000000000..45425355086 --- /dev/null +++ b/testdata/baselines/reference/tsc/commandLine/malformed-tsconfig-property-without-value.js @@ -0,0 +1,51 @@ +currentDirectory::/home/src/workspaces/project +useCaseSensitiveFileNames::true +Input:: +//// [/home/src/workspaces/project/index.ts] *new* + +//// [/home/src/workspaces/project/tsconfig.json] *new* +{"" } + +tsgo +ExitStatus:: DiagnosticsPresent_OutputsGenerated +Output:: +tsconfig.json:1:4 - error TS1328: Property value can only be string literal, numeric literal, 'true', 'false', 'null', object literal or array literal. + +1 {"" } +   ~ + +tsconfig.json:1:5 - error TS1005: ':' expected. + +1 {"" } +   ~ + + +Found 2 errors in the same file, starting at: tsconfig.json:1 + +//// [/home/src/tslibs/TS/Lib/lib.es2025.full.d.ts] *Lib* +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +interface SymbolConstructor { + (desc?: string | number): symbol; + for(name: string): symbol; + readonly toStringTag: symbol; +} +declare var Symbol: SymbolConstructor; +interface Symbol { + readonly [Symbol.toStringTag]: string; +} +declare const console: { log(msg: any): void; }; +//// [/home/src/workspaces/project/index.js] *new* +"use strict"; + + From 8483220d13aecd5627d5260dcc3d2e3933c3135e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:55:27 +0000 Subject: [PATCH 3/3] Address malformed config review feedback Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/parser/parser.go | 7 +++++-- internal/tsoptions/tsconfigparsing.go | 8 +------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 4a3e16a8dc3..8bbde76097b 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -227,8 +227,11 @@ func (p *Parser) parseJSONText() *ast.SourceFile { } func getErrorSpanForNode(sourceText string, node *ast.Node) core.TextRange { - pos := scanner.SkipTrivia(sourceText, node.Pos()) - return core.NewTextRange(min(pos, node.End()), max(pos, node.End())) + pos := node.Pos() + if !ast.NodeIsMissing(node) { + pos = scanner.SkipTrivia(sourceText, pos) + } + return core.NewTextRange(pos, node.End()) } func (p *Parser) validateJsonValue(sourceFile *ast.SourceFile, valueExpression *ast.Expression) { diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go index ae6bf8a6e96..b1e1955b1f9 100644 --- a/internal/tsoptions/tsconfigparsing.go +++ b/internal/tsoptions/tsconfigparsing.go @@ -261,13 +261,7 @@ func parseOwnConfigOfJsonSourceFile( onPropertySet, }, ) - for _, diagnostic := range err { - if !slices.ContainsFunc(sourceFile.Diagnostics(), func(parseDiagnostic *ast.Diagnostic) bool { - return parseDiagnostic.Code() == diagnostic.Code() && parseDiagnostic.Pos() == diagnostic.Pos() - }) { - errors = append(errors, diagnostic) - } - } + errors = append(errors, err...) // if len(rootCompilerOptions) != 0 && json != nil && json.CompilerOptions != nil { // errors = append(errors, ast.NewDiagnostic(sourceFile, rootCompilerOptions[0], diagnostics.X_0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file)) // }