From 748cef7a5dcce6589a365f3ce9858a7f52d8a7a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Oct 2025 14:54:23 +0000 Subject: [PATCH 1/4] Initial plan From f17bf49bae21d76f6c000bd2dc01b054b42073ad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Oct 2025 15:24:13 +0000 Subject: [PATCH 2/4] Fix --customConditions null not being respected When --customConditions null is passed on command line, it should override any value in tsconfig.json. This fix: - Adds a new parameter to pass raw command line options through config parsing - Updates mergeCompilerOptions to handle command line raw options correctly - Adds test to verify customConditions null override behavior Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/compiler/host.go | 2 +- internal/execute/build/host.go | 2 +- internal/execute/tsc.go | 7 ++- internal/project/configfileregistrybuilder.go | 2 +- internal/tsoptions/commandlineparser_test.go | 43 ++++++++++++++++ internal/tsoptions/parsinghelpers.go | 8 +++ internal/tsoptions/tsconfigparsing.go | 51 +++++++++++++++++-- 7 files changed, 107 insertions(+), 8 deletions(-) diff --git a/internal/compiler/host.go b/internal/compiler/host.go index 68f3cf620a..5d523a9ab3 100644 --- a/internal/compiler/host.go +++ b/internal/compiler/host.go @@ -83,6 +83,6 @@ func (h *compilerHost) GetSourceFile(opts ast.SourceFileParseOptions) *ast.Sourc } func (h *compilerHost) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine { - commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, nil, h, h.extendedConfigCache) + commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, nil, nil /*optionsRaw*/, h, h.extendedConfigCache) return commandLine } diff --git a/internal/execute/build/host.go b/internal/execute/build/host.go index 91f50aa59c..6c21169155 100644 --- a/internal/execute/build/host.go +++ b/internal/execute/build/host.go @@ -59,7 +59,7 @@ func (h *host) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile { func (h *host) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine { return h.resolvedReferences.loadOrStoreNew(path, func(path tspath.Path) *tsoptions.ParsedCommandLine { configStart := h.orchestrator.opts.Sys.Now() - commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, h.orchestrator.opts.Command.CompilerOptions, h, &h.extendedConfigCache) + commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, h.orchestrator.opts.Command.CompilerOptions, nil /*optionsRaw*/, h, &h.extendedConfigCache) configTime := h.orchestrator.opts.Sys.Now().Sub(configStart) h.configTimes.Store(path, configTime) return commandLine diff --git a/internal/execute/tsc.go b/internal/execute/tsc.go index 65bf8d43bb..d4b40f0435 100644 --- a/internal/execute/tsc.go +++ b/internal/execute/tsc.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/diagnostics" @@ -173,7 +174,11 @@ func tscCompilation(sys tsc.System, commandLine *tsoptions.ParsedCommandLine, te var compileTimes tsc.CompileTimes if configFileName != "" { configStart := sys.Now() - configParseResult, errors := tsoptions.GetParsedCommandLineOfConfigFile(configFileName, compilerOptionsFromCommandLine, sys, extendedConfigCache) + var commandLineRaw *collections.OrderedMap[string, any] + if raw, ok := commandLine.Raw.(*collections.OrderedMap[string, any]); ok { + commandLineRaw = raw + } + configParseResult, errors := tsoptions.GetParsedCommandLineOfConfigFileWithRaw(configFileName, compilerOptionsFromCommandLine, commandLineRaw, sys, extendedConfigCache) compileTimes.ConfigTime = sys.Now().Sub(configStart) if len(errors) != 0 { // these are unrecoverable errors--exit to report them as diagnostics diff --git a/internal/project/configfileregistrybuilder.go b/internal/project/configfileregistrybuilder.go index a4b5a7ff6d..9d154a4193 100644 --- a/internal/project/configfileregistrybuilder.go +++ b/internal/project/configfileregistrybuilder.go @@ -106,7 +106,7 @@ func (c *configFileRegistryBuilder) reloadIfNeeded(entry *configFileEntry, fileN entry.commandLine = entry.commandLine.ReloadFileNamesOfParsedCommandLine(c.fs.fs) case PendingReloadFull: logger.Log("Loading config file: " + fileName) - entry.commandLine, _ = tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, nil, c, c) + entry.commandLine, _ = tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, nil, nil /*optionsRaw*/, c, c) c.updateExtendingConfigs(path, entry.commandLine, entry.commandLine) c.updateRootFilesWatch(fileName, entry) logger.Log("Finished loading config file") diff --git a/internal/tsoptions/commandlineparser_test.go b/internal/tsoptions/commandlineparser_test.go index 9caf562d17..6634d66a4f 100644 --- a/internal/tsoptions/commandlineparser_test.go +++ b/internal/tsoptions/commandlineparser_test.go @@ -8,6 +8,7 @@ import ( "github.com/go-json-experiment/json" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/diagnosticwriter" @@ -86,6 +87,48 @@ func TestCommandLineParseResult(t *testing.T) { } } +func TestCustomConditionsNullOverride(t *testing.T) { + t.Parallel() + + files := map[string]string{ + "/project/tsconfig.json": `{ + "compilerOptions": { + "customConditions": ["condition1", "condition2"] + } +}`, + "/project/index.ts": `console.log("Hello, World!");`, + } + + host := tsoptionstest.NewVFSParseConfigHost(files, "/project", true) + + // Parse command line with --customConditions null + cmdLine := tsoptions.ParseCommandLine([]string{"--project", "/project", "--customConditions", "null"}, host) + + // Check that the raw options contain null for customConditions + if rawMap, ok := cmdLine.Raw.(*collections.OrderedMap[string, any]); ok { + customConditionsRaw, exists := rawMap.Get("customConditions") + assert.Assert(t, exists, "customConditions should exist in raw options") + assert.Assert(t, customConditionsRaw == nil, "customConditions should be nil in raw options, got: %v", customConditionsRaw) + } else { + t.Fatal("Raw options should be an OrderedMap") + } + + // Now parse the config file with the command line options + parsedConfig, errors := tsoptions.GetParsedCommandLineOfConfigFileWithRaw( + "/project/tsconfig.json", + cmdLine.CompilerOptions(), + cmdLine.Raw.(*collections.OrderedMap[string, any]), + host, + nil, + ) + + assert.Assert(t, len(errors) == 0, "Should not have errors: %v", errors) + + // Check that customConditions is nil (overridden by command line) + customConditions := parsedConfig.CompilerOptions().CustomConditions + assert.Assert(t, customConditions == nil, "customConditions should be nil after override, got: %v", customConditions) +} + func TestParseCommandLineVerifyNull(t *testing.T) { t.Parallel() repo.SkipIfNoTypeScriptSubmodule(t) diff --git a/internal/tsoptions/parsinghelpers.go b/internal/tsoptions/parsinghelpers.go index bf16518be2..0b2fc249b5 100644 --- a/internal/tsoptions/parsinghelpers.go +++ b/internal/tsoptions/parsinghelpers.go @@ -545,6 +545,7 @@ func mergeCompilerOptions(targetOptions, sourceOptions *core.CompilerOptions, ra var explicitNullFields collections.Set[string] if rawSource != nil { if rawMap, ok := rawSource.(*collections.OrderedMap[string, any]); ok { + // For tsconfig.json, options are nested under "compilerOptions" if compilerOptionsRaw, exists := rawMap.Get("compilerOptions"); exists { if compilerOptionsMap, ok := compilerOptionsRaw.(*collections.OrderedMap[string, any]); ok { for key, value := range compilerOptionsMap.Entries() { @@ -553,6 +554,13 @@ func mergeCompilerOptions(targetOptions, sourceOptions *core.CompilerOptions, ra } } } + } else { + // For command line options, the map IS the options directly + for key, value := range rawMap.Entries() { + if value == nil { + explicitNullFields.Add(key) + } + } } } } diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go index 9ccef5af8d..1723f50677 100644 --- a/internal/tsoptions/tsconfigparsing.go +++ b/internal/tsoptions/tsconfigparsing.go @@ -691,7 +691,24 @@ func ParseJsonSourceFileConfigFileContent( extendedConfigCache ExtendedConfigCache, ) *ParsedCommandLine { // tracing?.push(tracing.Phase.Parse, "parseJsonSourceFileConfigFileContent", { path: sourceFile.fileName }); - result := parseJsonConfigFileContentWorker(nil /*json*/, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache) + result := parseJsonConfigFileContentWorker(nil /*json*/, sourceFile, host, basePath, existingOptions, nil /*existingOptionsRaw*/, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache) + // tracing?.pop(); + return result +} + +func ParseJsonSourceFileConfigFileContentWithRaw( + sourceFile *TsConfigSourceFile, + host ParseConfigHost, + basePath string, + existingOptions *core.CompilerOptions, + existingOptionsRaw *collections.OrderedMap[string, any], + configFileName string, + resolutionStack []tspath.Path, + extraFileExtensions []FileExtensionInfo, + extendedConfigCache ExtendedConfigCache, +) *ParsedCommandLine { + // tracing?.push(tracing.Phase.Parse, "parseJsonSourceFileConfigFileContent", { path: sourceFile.fileName }); + result := parseJsonConfigFileContentWorker(nil /*json*/, sourceFile, host, basePath, existingOptions, existingOptionsRaw, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache) // tracing?.pop(); return result } @@ -829,7 +846,7 @@ func convertPropertyValueToJson(sourceFile *ast.SourceFile, valueExpression *ast // host: Instance of ParseConfigHost used to enumerate files in folder. // basePath: A root directory to resolve relative path entries in the config file to. e.g. outDir func ParseJsonConfigFileContent(json any, host ParseConfigHost, basePath string, existingOptions *core.CompilerOptions, configFileName string, resolutionStack []tspath.Path, extraFileExtensions []FileExtensionInfo, extendedConfigCache ExtendedConfigCache) *ParsedCommandLine { - result := parseJsonConfigFileContentWorker(parseJsonToStringKey(json), nil /*sourceFile*/, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache) + result := parseJsonConfigFileContentWorker(parseJsonToStringKey(json), nil /*sourceFile*/, host, basePath, existingOptions, nil /*existingOptionsRaw*/, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache) return result } @@ -1127,6 +1144,7 @@ func parseJsonConfigFileContentWorker( host ParseConfigHost, basePath string, existingOptions *core.CompilerOptions, + existingOptionsRaw *collections.OrderedMap[string, any], configFileName string, resolutionStack []tspath.Path, extraFileExtensions []FileExtensionInfo, @@ -1144,7 +1162,7 @@ func parseJsonConfigFileContentWorker( var errors []*ast.Diagnostic resolutionStackString := []string{} parsedConfig, errors := parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStackString, extendedConfigCache) - mergeCompilerOptions(parsedConfig.options, existingOptions, nil) + mergeCompilerOptions(parsedConfig.options, existingOptions, existingOptionsRaw) handleOptionConfigDirTemplateSubstitution(parsedConfig.options, basePathForFileNames) rawConfig := parseJsonToStringKey(parsedConfig.raw) if configFileName != "" && parsedConfig.options != nil { @@ -1743,13 +1761,25 @@ func GetParsedCommandLineOfConfigFile( extendedConfigCache ExtendedConfigCache, ) (*ParsedCommandLine, []*ast.Diagnostic) { configFileName = tspath.GetNormalizedAbsolutePath(configFileName, sys.GetCurrentDirectory()) - return GetParsedCommandLineOfConfigFilePath(configFileName, tspath.ToPath(configFileName, sys.GetCurrentDirectory(), sys.FS().UseCaseSensitiveFileNames()), options, sys, extendedConfigCache) + return GetParsedCommandLineOfConfigFilePath(configFileName, tspath.ToPath(configFileName, sys.GetCurrentDirectory(), sys.FS().UseCaseSensitiveFileNames()), options, nil /*optionsRaw*/, sys, extendedConfigCache) +} + +func GetParsedCommandLineOfConfigFileWithRaw( + configFileName string, + options *core.CompilerOptions, + optionsRaw *collections.OrderedMap[string, any], + sys ParseConfigHost, + extendedConfigCache ExtendedConfigCache, +) (*ParsedCommandLine, []*ast.Diagnostic) { + configFileName = tspath.GetNormalizedAbsolutePath(configFileName, sys.GetCurrentDirectory()) + return GetParsedCommandLineOfConfigFilePath(configFileName, tspath.ToPath(configFileName, sys.GetCurrentDirectory(), sys.FS().UseCaseSensitiveFileNames()), options, optionsRaw, sys, extendedConfigCache) } func GetParsedCommandLineOfConfigFilePath( configFileName string, path tspath.Path, options *core.CompilerOptions, + optionsRaw *collections.OrderedMap[string, any], sys ParseConfigHost, extendedConfigCache ExtendedConfigCache, ) (*ParsedCommandLine, []*ast.Diagnostic) { @@ -1763,6 +1793,19 @@ func GetParsedCommandLineOfConfigFilePath( tsConfigSourceFile := NewTsconfigSourceFileFromFilePath(configFileName, path, configFileText) // tsConfigSourceFile.resolvedPath = tsConfigSourceFile.FileName() // tsConfigSourceFile.originalFileName = tsConfigSourceFile.FileName() + if optionsRaw != nil { + return ParseJsonSourceFileConfigFileContentWithRaw( + tsConfigSourceFile, + sys, + tspath.GetDirectoryPath(configFileName), + options, + optionsRaw, + configFileName, + nil, + nil, + extendedConfigCache, + ), nil + } return ParseJsonSourceFileConfigFileContent( tsConfigSourceFile, sys, From ef3071ce302daf41ad327b2590b281356933fe3a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Oct 2025 15:35:24 +0000 Subject: [PATCH 3/4] Fix nil pointer dereference and update baseline - Handle nil OrderedMap in mergeCompilerOptions - Handle nil targetOptions in mergeCompilerOptions - Accept baseline for composite null test (correct behavior) Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/tsoptions/parsinghelpers.go | 5 +- ...-setting-composite-null-on-command-line.js | 59 ------------------- 2 files changed, 4 insertions(+), 60 deletions(-) diff --git a/internal/tsoptions/parsinghelpers.go b/internal/tsoptions/parsinghelpers.go index 0b2fc249b5..0d5fa73690 100644 --- a/internal/tsoptions/parsinghelpers.go +++ b/internal/tsoptions/parsinghelpers.go @@ -540,11 +540,14 @@ func mergeCompilerOptions(targetOptions, sourceOptions *core.CompilerOptions, ra if sourceOptions == nil { return targetOptions } + if targetOptions == nil { + targetOptions = &core.CompilerOptions{} + } // Collect explicitly null field names from raw JSON var explicitNullFields collections.Set[string] if rawSource != nil { - if rawMap, ok := rawSource.(*collections.OrderedMap[string, any]); ok { + if rawMap, ok := rawSource.(*collections.OrderedMap[string, any]); ok && rawMap != nil { // For tsconfig.json, options are nested under "compilerOptions" if compilerOptionsRaw, exists := rawMap.Get("compilerOptions"); exists { if compilerOptionsMap, ok := compilerOptionsRaw.(*collections.OrderedMap[string, any]); ok { diff --git a/testdata/baselines/reference/tsc/composite/when-setting-composite-null-on-command-line.js b/testdata/baselines/reference/tsc/composite/when-setting-composite-null-on-command-line.js index 285f20672a..c16f2e1dd8 100644 --- a/testdata/baselines/reference/tsc/composite/when-setting-composite-null-on-command-line.js +++ b/testdata/baselines/reference/tsc/composite/when-setting-composite-null-on-command-line.js @@ -41,69 +41,10 @@ interface Symbol { readonly [Symbol.toStringTag]: string; } declare const console: { log(msg: any): void; }; -//// [/home/src/workspaces/project/src/main.d.ts] *new* -export declare const x = 10; - //// [/home/src/workspaces/project/src/main.js] *new* "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.x = void 0; exports.x = 10; -//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *new* -{"version":"FakeTSVersion","root":[2],"fileNames":["lib.d.ts","./src/main.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"28e8748a7acd58f4f59388926e914f86-export const x = 10;","signature":"f9b4154a9a5944099ecf197d4519d083-export declare const x = 10;\n","impliedNodeFormat":1}],"options":{"composite":true,"module":1,"target":1},"latestChangedDtsFile":"./src/main.d.ts"} -//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new* -{ - "version": "FakeTSVersion", - "root": [ - { - "files": [ - "./src/main.ts" - ], - "original": 2 - } - ], - "fileNames": [ - "lib.d.ts", - "./src/main.ts" - ], - "fileInfos": [ - { - "fileName": "lib.d.ts", - "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", - "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", - "affectsGlobalScope": true, - "impliedNodeFormat": "CommonJS", - "original": { - "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };", - "affectsGlobalScope": true, - "impliedNodeFormat": 1 - } - }, - { - "fileName": "./src/main.ts", - "version": "28e8748a7acd58f4f59388926e914f86-export const x = 10;", - "signature": "f9b4154a9a5944099ecf197d4519d083-export declare const x = 10;\n", - "impliedNodeFormat": "CommonJS", - "original": { - "version": "28e8748a7acd58f4f59388926e914f86-export const x = 10;", - "signature": "f9b4154a9a5944099ecf197d4519d083-export declare const x = 10;\n", - "impliedNodeFormat": 1 - } - } - ], - "options": { - "composite": true, - "module": 1, - "target": 1 - }, - "latestChangedDtsFile": "./src/main.d.ts", - "size": 1123 -} -tsconfig.json:: -SemanticDiagnostics:: -*refresh* /home/src/tslibs/TS/Lib/lib.d.ts -*refresh* /home/src/workspaces/project/src/main.ts -Signatures:: -(stored at emit) /home/src/workspaces/project/src/main.ts From aa4a6304ed2f3774e9e76a49838447930d4d8683 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Oct 2025 16:42:40 +0000 Subject: [PATCH 4/4] Fix nil targetOptions by initializing options in parseConfig error case Instead of checking for nil in mergeCompilerOptions, properly initialize options to empty struct when circularity error is detected in parseConfig. This ensures targetOptions is never nil when mergeCompilerOptions is called. Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/tsoptions/parsinghelpers.go | 3 --- internal/tsoptions/tsconfigparsing.go | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/internal/tsoptions/parsinghelpers.go b/internal/tsoptions/parsinghelpers.go index 0d5fa73690..71d7bb8ed0 100644 --- a/internal/tsoptions/parsinghelpers.go +++ b/internal/tsoptions/parsinghelpers.go @@ -540,9 +540,6 @@ func mergeCompilerOptions(targetOptions, sourceOptions *core.CompilerOptions, ra if sourceOptions == nil { return targetOptions } - if targetOptions == nil { - targetOptions = &core.CompilerOptions{} - } // Collect explicitly null field names from raw JSON var explicitNullFields collections.Set[string] diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go index 1723f50677..fb5a3c2598 100644 --- a/internal/tsoptions/tsconfigparsing.go +++ b/internal/tsoptions/tsconfigparsing.go @@ -1011,11 +1011,11 @@ func parseConfig( var result *parsedTsconfig errors = append(errors, ast.NewCompilerDiagnostic(diagnostics.Circularity_detected_while_resolving_configuration_Colon_0)) if json.Size() == 0 { - result = &parsedTsconfig{raw: json} + result = &parsedTsconfig{raw: json, options: &core.CompilerOptions{}} } else { rawResult, err := convertToObject(sourceFile.SourceFile) errors = append(errors, err...) - result = &parsedTsconfig{raw: rawResult} + result = &parsedTsconfig{raw: rawResult, options: &core.CompilerOptions{}} } return result, errors }