From 52e7108cf833c4023d985768fef69583919e8533 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Thu, 7 Aug 2025 11:28:57 -0700 Subject: [PATCH 1/3] use path for task to fix crash --- internal/compiler/fileloader.go | 40 +++- internal/compiler/fileloadertask.go | 10 +- internal/compiler/parsetask.go | 21 ++- .../compiler/projectreferencefilemapper.go | 4 +- .../compiler/projectreferenceparsetask.go | 13 +- internal/execute/testsys_test.go | 4 +- internal/execute/tsc_test.go | 48 +++++ internal/execute/tsctestrunner_test.go | 15 +- ...mental-with-case-insensitive-file-names.js | 171 ++++++++++++++++++ 9 files changed, 293 insertions(+), 33 deletions(-) create mode 100644 testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js diff --git a/internal/compiler/fileloader.go b/internal/compiler/fileloader.go index cc1d113759..ccbe4d8825 100644 --- a/internal/compiler/fileloader.go +++ b/internal/compiler/fileloader.go @@ -239,7 +239,14 @@ func (p *fileLoader) addRootTasks(files []string, isLib bool) { for _, fileName := range files { absPath := tspath.GetNormalizedAbsolutePath(fileName, p.opts.Host.GetCurrentDirectory()) if core.Tristate.IsTrue(p.opts.Config.CompilerOptions().AllowNonTsExtensions) || slices.Contains(p.supportedExtensions, tspath.TryGetExtensionFromPath(absPath)) { - p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: absPath, isLib: isLib, root: true}) + p.rootTasks = append( + p.rootTasks, + &parseTask{ + normalizedFilePath: absPath, + isLib: isLib, + root: true, + path: p.toPath(absPath), + }) } } } @@ -253,7 +260,14 @@ func (p *fileLoader) addAutomaticTypeDirectiveTasks() { containingDirectory = p.opts.Host.GetCurrentDirectory() } containingFileName := tspath.CombinePaths(containingDirectory, module.InferredTypesContainingFile) - p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: containingFileName, isLib: false, isForAutomaticTypeDirective: true}) + p.rootTasks = append( + p.rootTasks, + &parseTask{ + normalizedFilePath: containingFileName, + isLib: false, + isForAutomaticTypeDirective: true, + path: p.toPath(containingFileName), + }) } func (p *fileLoader) resolveAutomaticTypeDirectives(containingFileName string) ( @@ -290,7 +304,7 @@ func (p *fileLoader) addProjectReferenceTasks() { return } - rootTasks := createProjectReferenceParseTasks(projectReferences) + rootTasks := createProjectReferenceParseTasks(projectReferences, p) p.projectReferenceParseTasks.runAndWait(p, rootTasks) p.projectReferenceFileMapper.init(p, rootTasks) @@ -305,12 +319,24 @@ func (p *fileLoader) addProjectReferenceTasks() { } if p.opts.canUseProjectReferenceSource() { for _, fileName := range resolved.FileNames() { - p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: fileName, isLib: false}) + p.rootTasks = append( + p.rootTasks, + &parseTask{ + normalizedFilePath: fileName, + isLib: false, + path: p.toPath(fileName), + }) } } else { for outputDts := range resolved.GetOutputDeclarationFileNames() { if outputDts != "" { - p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: outputDts, isLib: false}) + p.rootTasks = append( + p.rootTasks, + &parseTask{ + normalizedFilePath: outputDts, + isLib: false, + path: p.toPath(outputDts), + }) } } } @@ -406,7 +432,7 @@ func (p *fileLoader) resolveTypeReferenceDirectives(t *parseTask) { increaseDepth: resolved.IsExternalLibraryImport, elideOnDepth: false, isFromExternalLibrary: resolved.IsExternalLibraryImport, - }, false) + }, false, p) } } @@ -497,7 +523,7 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) { increaseDepth: resolvedModule.IsExternalLibraryImport, elideOnDepth: isJsFileFromNodeModules, isFromExternalLibrary: resolvedModule.IsExternalLibraryImport, - }, false) + }, false, p) } } diff --git a/internal/compiler/fileloadertask.go b/internal/compiler/fileloadertask.go index cbee6db679..0efae6a6ad 100644 --- a/internal/compiler/fileloadertask.go +++ b/internal/compiler/fileloadertask.go @@ -11,7 +11,7 @@ import ( type fileLoaderWorkerTask[T any] interface { comparable - FileName() string + Path() tspath.Path isLoaded() bool load(loader *fileLoader) getSubTasks() []T @@ -24,7 +24,7 @@ type fileLoaderWorkerTask[T any] interface { type fileLoaderWorker[K fileLoaderWorkerTask[K]] struct { wg core.WorkGroup - tasksByFileName collections.SyncMap[string, *queuedTask[K]] + tasksByFilePath collections.SyncMap[tspath.Path, *queuedTask[K]] maxDepth int } @@ -44,7 +44,7 @@ func (w *fileLoaderWorker[K]) start(loader *fileLoader, tasks []K, depth int, is for i, task := range tasks { taskIsFromExternalLibrary := isFromExternalLibrary || task.isFromExternalLibrary() newTask := &queuedTask[K]{task: task, lowestDepth: math.MaxInt} - loadedTask, loaded := w.tasksByFileName.LoadOrStore(task.FileName(), newTask) + loadedTask, loaded := w.tasksByFilePath.LoadOrStore(task.Path(), newTask) task = loadedTask.task if loaded { tasks[i] = task @@ -93,7 +93,7 @@ func (w *fileLoaderWorker[K]) start(loader *fileLoader, tasks []K, depth int, is func (w *fileLoaderWorker[K]) collect(loader *fileLoader, tasks []K, iterate func(K, []tspath.Path)) []tspath.Path { // Mark all tasks we saw as external after the fact. - w.tasksByFileName.Range(func(key string, value *queuedTask[K]) bool { + w.tasksByFilePath.Range(func(_ tspath.Path, value *queuedTask[K]) bool { if value.fromExternalLibrary { value.task.markFromExternalLibrary() } @@ -115,7 +115,7 @@ func (w *fileLoaderWorker[K]) collectWorker(loader *fileLoader, tasks []K, itera subResults = w.collectWorker(loader, subTasks, iterate, seen) } iterate(task, subResults) - results = append(results, loader.toPath(task.FileName())) + results = append(results, task.Path()) } return results } diff --git a/internal/compiler/parsetask.go b/internal/compiler/parsetask.go index 9d7045bfc4..6e6d23d303 100644 --- a/internal/compiler/parsetask.go +++ b/internal/compiler/parsetask.go @@ -37,6 +37,10 @@ func (t *parseTask) FileName() string { return t.normalizedFilePath } +func (t *parseTask) FilePath() tspath.Path { + return t.path +} + func (t *parseTask) Path() tspath.Path { return t.path } @@ -70,7 +74,7 @@ func (t *parseTask) load(loader *fileLoader) { for _, ref := range file.ReferencedFiles { resolvedPath := loader.resolveTripleslashPathReference(ref.FileName, file.FileName()) - t.addSubTask(resolvedPath, false) + t.addSubTask(resolvedPath, false, loader) } compilerOptions := loader.opts.Config.CompilerOptions() @@ -79,7 +83,7 @@ func (t *parseTask) load(loader *fileLoader) { if compilerOptions.NoLib != core.TSTrue { for _, lib := range file.LibReferenceDirectives { if name, ok := tsoptions.GetLibFileName(lib.FileName); ok { - t.addSubTask(resolvedRef{fileName: loader.pathForLibFile(name)}, true) + t.addSubTask(resolvedRef{fileName: loader.pathForLibFile(name)}, true, loader) } } } @@ -90,14 +94,20 @@ func (t *parseTask) load(loader *fileLoader) { func (t *parseTask) redirect(loader *fileLoader, fileName string) { t.isRedirected = true // increaseDepth and elideOnDepth are not copied to redirects, otherwise their depth would be double counted. - t.subTasks = []*parseTask{{normalizedFilePath: tspath.NormalizePath(fileName), isLib: t.isLib, fromExternalLibrary: t.fromExternalLibrary}} + normalizedFilePath := tspath.NormalizePath(fileName) + t.subTasks = []*parseTask{{ + normalizedFilePath: normalizedFilePath, + isLib: t.isLib, + fromExternalLibrary: t.fromExternalLibrary, + path: loader.toPath(normalizedFilePath), + }} } func (t *parseTask) loadAutomaticTypeDirectives(loader *fileLoader) { toParseTypeRefs, typeResolutionsInFile := loader.resolveAutomaticTypeDirectives(t.normalizedFilePath) t.typeResolutionsInFile = typeResolutionsInFile for _, typeResolution := range toParseTypeRefs { - t.addSubTask(typeResolution, false) + t.addSubTask(typeResolution, false, loader) } } @@ -108,7 +118,7 @@ type resolvedRef struct { isFromExternalLibrary bool } -func (t *parseTask) addSubTask(ref resolvedRef, isLib bool) { +func (t *parseTask) addSubTask(ref resolvedRef, isLib bool, loader *fileLoader) { normalizedFilePath := tspath.NormalizePath(ref.fileName) subTask := &parseTask{ normalizedFilePath: normalizedFilePath, @@ -116,6 +126,7 @@ func (t *parseTask) addSubTask(ref resolvedRef, isLib bool) { increaseDepth: ref.increaseDepth, elideOnDepth: ref.elideOnDepth, fromExternalLibrary: ref.isFromExternalLibrary, + path: loader.toPath(normalizedFilePath), } t.subTasks = append(t.subTasks, subTask) } diff --git a/internal/compiler/projectreferencefilemapper.go b/internal/compiler/projectreferencefilemapper.go index 319c2ab477..a83e8fd17e 100644 --- a/internal/compiler/projectreferencefilemapper.go +++ b/internal/compiler/projectreferencefilemapper.go @@ -26,7 +26,7 @@ type projectReferenceFileMapper struct { } func (mapper *projectReferenceFileMapper) init(loader *fileLoader, rootTasks []*projectReferenceParseTask) { - totalReferences := loader.projectReferenceParseTasks.tasksByFileName.Size() + 1 + totalReferences := loader.projectReferenceParseTasks.tasksByFilePath.Size() + 1 mapper.loader = loader mapper.configToProjectReference = make(map[tspath.Path]*tsoptions.ParsedCommandLine, totalReferences) mapper.referencesInConfigFile = make(map[tspath.Path][]tspath.Path, totalReferences) @@ -36,7 +36,7 @@ func (mapper *projectReferenceFileMapper) init(loader *fileLoader, rootTasks []* loader, rootTasks, func(task *projectReferenceParseTask, referencesInConfig []tspath.Path) { - path := loader.toPath(task.configName) + path := task.Path() mapper.configToProjectReference[path] = task.resolved if task.resolved == nil || mapper.opts.Config.ConfigFile == task.resolved.ConfigFile { return diff --git a/internal/compiler/projectreferenceparsetask.go b/internal/compiler/projectreferenceparsetask.go index 8428a078ec..2898c36a85 100644 --- a/internal/compiler/projectreferenceparsetask.go +++ b/internal/compiler/projectreferenceparsetask.go @@ -3,23 +3,25 @@ package compiler import ( "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/tsoptions" + "github.com/microsoft/typescript-go/internal/tspath" ) type projectReferenceParseTask struct { loaded bool + configPath tspath.Path configName string resolved *tsoptions.ParsedCommandLine subTasks []*projectReferenceParseTask } -func (t *projectReferenceParseTask) FileName() string { - return t.configName +func (t *projectReferenceParseTask) Path() tspath.Path { + return t.configPath } func (t *projectReferenceParseTask) load(loader *fileLoader) { t.loaded = true - t.resolved = loader.opts.Host.GetResolvedProjectReference(t.configName, loader.toPath(t.configName)) + t.resolved = loader.opts.Host.GetResolvedProjectReference(t.configName, t.configPath) if t.resolved == nil { return } @@ -32,7 +34,7 @@ func (t *projectReferenceParseTask) load(loader *fileLoader) { if len(subReferences) == 0 { return } - t.subTasks = createProjectReferenceParseTasks(subReferences) + t.subTasks = createProjectReferenceParseTasks(subReferences, loader) } func (t *projectReferenceParseTask) getSubTasks() []*projectReferenceParseTask { @@ -61,10 +63,11 @@ func (t *projectReferenceParseTask) isFromExternalLibrary() bool { func (t *projectReferenceParseTask) markFromExternalLibrary() {} -func createProjectReferenceParseTasks(projectReferences []string) []*projectReferenceParseTask { +func createProjectReferenceParseTasks(projectReferences []string, loader *fileLoader) []*projectReferenceParseTask { return core.Map(projectReferences, func(configName string) *projectReferenceParseTask { return &projectReferenceParseTask{ configName: configName, + configPath: loader.toPath(configName), } }) } diff --git a/internal/execute/testsys_test.go b/internal/execute/testsys_test.go index 41a499bb94..46a4658ad9 100644 --- a/internal/execute/testsys_test.go +++ b/internal/execute/testsys_test.go @@ -50,14 +50,14 @@ interface Symbol { declare const console: { log(msg: any): void; }; `) -func newTestSys(fileOrFolderList FileMap, cwd string) *testSys { +func newTestSys(fileOrFolderList FileMap, cwd string, useCaseSensitiveFileNames bool) *testSys { if cwd == "" { cwd = "/home/src/workspaces/project" } sys := &testSys{ fs: &incrementaltestutil.FsHandlingBuildInfo{ FS: &testFs{ - FS: vfstest.FromMap(fileOrFolderList, true /*useCaseSensitiveFileNames*/), + FS: vfstest.FromMap(fileOrFolderList, useCaseSensitiveFileNames), }, }, defaultLibraryPath: tscLibPath, diff --git a/internal/execute/tsc_test.go b/internal/execute/tsc_test.go index cc72906eba..4709b7d2fd 100644 --- a/internal/execute/tsc_test.go +++ b/internal/execute/tsc_test.go @@ -130,6 +130,54 @@ func TestTscCommandline(t *testing.T) { subScenario: "Parse watch interval option without tsconfig.json", commandLineArgs: []string{"-w", "--watchInterval", "1000"}, }, + { + subScenario: "Compile incremental with case insensitive file names", + commandLineArgs: []string{"-p", "."}, + files: FileMap{ + "/home/project/tsconfig.json": stringtestutil.Dedent(` + { + "compilerOptions": { + "incremental": true + }, + }`), + "/home/project/src/index.ts": stringtestutil.Dedent(` + import type { Foo1 } from 'lib1'; + import type { Foo2 } from 'lib2'; + export const foo1: Foo1 = { foo: "a" }; + export const foo2: Foo2 = { foo: "b" };`), + "/home/node_modules/lib1/index.d.ts": stringtestutil.Dedent(` + import type { Foo } from 'someLib'; + export type { Foo as Foo1 };`), + "/home/node_modules/lib1/package.json": stringtestutil.Dedent(` + { + "name": "lib1" + }`), + "/home/node_modules/lib2/index.d.ts": stringtestutil.Dedent(` + import type { Foo } from 'somelib'; + export type { Foo as Foo2 }; + export declare const foo2: Foo;`), + "/home/node_modules/lib2/package.json": stringtestutil.Dedent(` + { + "name": "lib2" + } + `), + "/home/node_modules/someLib/index.d.ts": stringtestutil.Dedent(` + import type { Str } from 'otherLib'; + export type Foo = { foo: Str; };`), + "/home/node_modules/someLib/package.json": stringtestutil.Dedent(` + { + "name": "somelib" + }`), + "/home/node_modules/otherLib/index.d.ts": stringtestutil.Dedent(` + export type Str = string;`), + "/home/node_modules/otherLib/package.json": stringtestutil.Dedent(` + { + "name": "otherlib" + }`), + }, + cwd: "/home/project", + useCaseInsensitiveFileNames: true, + }, } for _, testCase := range testCases { diff --git a/internal/execute/tsctestrunner_test.go b/internal/execute/tsctestrunner_test.go index 6599851803..3c502458f1 100644 --- a/internal/execute/tsctestrunner_test.go +++ b/internal/execute/tsctestrunner_test.go @@ -29,11 +29,12 @@ var noChangeOnlyEdit = []*testTscEdit{ } type tscInput struct { - subScenario string - commandLineArgs []string - files FileMap - cwd string - edits []*testTscEdit + subScenario string + commandLineArgs []string + files FileMap + cwd string + edits []*testTscEdit + useCaseInsensitiveFileNames bool } func (test *tscInput) executeCommand(sys *testSys, baselineBuilder *strings.Builder, commandLineArgs []string) execute.CommandLineResult { @@ -64,7 +65,7 @@ func (test *tscInput) run(t *testing.T, scenario string) { t.Parallel() // initial test tsc compile baselineBuilder := &strings.Builder{} - sys := newTestSys(test.files, test.cwd) + sys := newTestSys(test.files, test.cwd, !test.useCaseInsensitiveFileNames) fmt.Fprint( baselineBuilder, "currentDirectory::", @@ -101,7 +102,7 @@ func (test *tscInput) run(t *testing.T, scenario string) { }) wg.Queue(func() { // Compute build with all the edits - nonIncrementalSys = newTestSys(test.files, test.cwd) + nonIncrementalSys = newTestSys(test.files, test.cwd, !test.useCaseInsensitiveFileNames) for i := range index + 1 { if test.edits[i].edit != nil { test.edits[i].edit(nonIncrementalSys) diff --git a/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js b/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js new file mode 100644 index 0000000000..621853ad4f --- /dev/null +++ b/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js @@ -0,0 +1,171 @@ +currentDirectory::/home/project +useCaseSensitiveFileNames::false +Input:: +//// [/home/node_modules/lib1/index.d.ts] *new* +import type { Foo } from 'someLib'; +export type { Foo as Foo1 }; +//// [/home/node_modules/lib1/package.json] *new* +{ + "name": "lib1" +} +//// [/home/node_modules/lib2/index.d.ts] *new* +import type { Foo } from 'somelib'; +export type { Foo as Foo2 }; +export declare const foo2: Foo; +//// [/home/node_modules/lib2/package.json] *new* +{ + "name": "lib2" +} +//// [/home/node_modules/otherLib/index.d.ts] *new* +export type Str = string; +//// [/home/node_modules/otherLib/package.json] *new* +{ + "name": "otherlib" +} +//// [/home/node_modules/someLib/index.d.ts] *new* +import type { Str } from 'otherLib'; +export type Foo = { foo: Str; }; +//// [/home/node_modules/someLib/package.json] *new* + { +"name": "somelib" + } +//// [/home/project/src/index.ts] *new* +import type { Foo1 } from 'lib1'; +import type { Foo2 } from 'lib2'; +export const foo1: Foo1 = { foo: "a" }; +export const foo2: Foo2 = { foo: "b" }; +//// [/home/project/tsconfig.json] *new* + { +"compilerOptions": { + "incremental": true +}, + } + +tsgo -p . +ExitStatus:: Success +Output:: +//// [/home/project/src/index.js] *new* +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.foo2 = exports.foo1 = void 0; +exports.foo1 = { foo: "a" }; +exports.foo2 = { foo: "b" }; + +//// [/home/project/tsconfig.tsbuildinfo] *new* +{"version":"FakeTSVersion","fileNames":["../src/tslibs/ts/lib/lib.d.ts","../node_modules/otherlib/index.d.ts","../node_modules/somelib/index.d.ts","../node_modules/lib1/index.d.ts","../node_modules/lib2/index.d.ts","./src/index.ts"],"fileInfos":[{"version":"eae9e83ef0f77eeb2e35dc9b91facce1-/// \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},"a40368814f37d4357a34c3f941f3e677-export type Str = string;","c83d508c75590e2f7051911d4a827ceb-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };","a508f6d5ab12f0c2168b5488ebbd34be-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };","528165de17b5f9f1dbbf984a062d9b57-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;","c367835e98822462afe5cacbac4d94c2-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };"],"fileIdsList":[[3],[2],[4,5]],"referencedMap":[[4,1],[5,1],[3,2],[6,3]]} +//// [/home/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new* +{ + "version": "FakeTSVersion", + "fileNames": [ + "../src/tslibs/ts/lib/lib.d.ts", + "../node_modules/otherlib/index.d.ts", + "../node_modules/somelib/index.d.ts", + "../node_modules/lib1/index.d.ts", + "../node_modules/lib2/index.d.ts", + "./src/index.ts" + ], + "fileInfos": [ + { + "fileName": "../src/tslibs/ts/lib/lib.d.ts", + "version": "eae9e83ef0f77eeb2e35dc9b91facce1-/// \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": "eae9e83ef0f77eeb2e35dc9b91facce1-/// \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": "eae9e83ef0f77eeb2e35dc9b91facce1-/// \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": "../node_modules/otherlib/index.d.ts", + "version": "a40368814f37d4357a34c3f941f3e677-export type Str = string;", + "signature": "a40368814f37d4357a34c3f941f3e677-export type Str = string;", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "../node_modules/somelib/index.d.ts", + "version": "c83d508c75590e2f7051911d4a827ceb-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };", + "signature": "c83d508c75590e2f7051911d4a827ceb-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "../node_modules/lib1/index.d.ts", + "version": "a508f6d5ab12f0c2168b5488ebbd34be-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };", + "signature": "a508f6d5ab12f0c2168b5488ebbd34be-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "../node_modules/lib2/index.d.ts", + "version": "528165de17b5f9f1dbbf984a062d9b57-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;", + "signature": "528165de17b5f9f1dbbf984a062d9b57-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;", + "impliedNodeFormat": "CommonJS" + }, + { + "fileName": "./src/index.ts", + "version": "c367835e98822462afe5cacbac4d94c2-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };", + "signature": "c367835e98822462afe5cacbac4d94c2-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };", + "impliedNodeFormat": "CommonJS" + } + ], + "fileIdsList": [ + [ + "../node_modules/somelib/index.d.ts" + ], + [ + "../node_modules/otherlib/index.d.ts" + ], + [ + "../node_modules/lib1/index.d.ts", + "../node_modules/lib2/index.d.ts" + ] + ], + "referencedMap": { + "../node_modules/lib1/index.d.ts": [ + "../node_modules/somelib/index.d.ts" + ], + "../node_modules/lib2/index.d.ts": [ + "../node_modules/somelib/index.d.ts" + ], + "../node_modules/somelib/index.d.ts": [ + "../node_modules/otherlib/index.d.ts" + ], + "./src/index.ts": [ + "../node_modules/lib1/index.d.ts", + "../node_modules/lib2/index.d.ts" + ] + }, + "size": 1681 +} +//// [/home/src/tslibs/TS/Lib/lib.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; }; + +SemanticDiagnostics:: +*refresh* /home/src/tslibs/TS/Lib/lib.d.ts +*refresh* /home/node_modules/otherLib/index.d.ts +*refresh* /home/node_modules/somelib/index.d.ts +*refresh* /home/node_modules/lib1/index.d.ts +*refresh* /home/node_modules/lib2/index.d.ts +*refresh* /home/project/src/index.ts +Signatures:: From d22b5dbe3f04884c3ab190e83b36bfced1839443 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Thu, 7 Aug 2025 12:58:50 -0700 Subject: [PATCH 2/3] rename property to ignoreCase and update baselines --- internal/execute/tsc_test.go | 4 +-- internal/execute/tsctestrunner_test.go | 16 +++++------ ...mental-with-case-insensitive-file-names.js | 28 +++++++++---------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/internal/execute/tsc_test.go b/internal/execute/tsc_test.go index 4709b7d2fd..4f134aa88c 100644 --- a/internal/execute/tsc_test.go +++ b/internal/execute/tsc_test.go @@ -175,8 +175,8 @@ func TestTscCommandline(t *testing.T) { "name": "otherlib" }`), }, - cwd: "/home/project", - useCaseInsensitiveFileNames: true, + cwd: "/home/project", + ignoreCase: true, }, } diff --git a/internal/execute/tsctestrunner_test.go b/internal/execute/tsctestrunner_test.go index 3c502458f1..16ea891d08 100644 --- a/internal/execute/tsctestrunner_test.go +++ b/internal/execute/tsctestrunner_test.go @@ -29,12 +29,12 @@ var noChangeOnlyEdit = []*testTscEdit{ } type tscInput struct { - subScenario string - commandLineArgs []string - files FileMap - cwd string - edits []*testTscEdit - useCaseInsensitiveFileNames bool + subScenario string + commandLineArgs []string + files FileMap + cwd string + edits []*testTscEdit + ignoreCase bool } func (test *tscInput) executeCommand(sys *testSys, baselineBuilder *strings.Builder, commandLineArgs []string) execute.CommandLineResult { @@ -65,7 +65,7 @@ func (test *tscInput) run(t *testing.T, scenario string) { t.Parallel() // initial test tsc compile baselineBuilder := &strings.Builder{} - sys := newTestSys(test.files, test.cwd, !test.useCaseInsensitiveFileNames) + sys := newTestSys(test.files, test.cwd, !test.ignoreCase) fmt.Fprint( baselineBuilder, "currentDirectory::", @@ -102,7 +102,7 @@ func (test *tscInput) run(t *testing.T, scenario string) { }) wg.Queue(func() { // Compute build with all the edits - nonIncrementalSys = newTestSys(test.files, test.cwd, !test.useCaseInsensitiveFileNames) + nonIncrementalSys = newTestSys(test.files, test.cwd, !test.ignoreCase) for i := range index + 1 { if test.edits[i].edit != nil { test.edits[i].edit(nonIncrementalSys) diff --git a/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js b/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js index 621853ad4f..2f4f63b1bc 100644 --- a/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js +++ b/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js @@ -52,7 +52,7 @@ exports.foo1 = { foo: "a" }; exports.foo2 = { foo: "b" }; //// [/home/project/tsconfig.tsbuildinfo] *new* -{"version":"FakeTSVersion","fileNames":["../src/tslibs/ts/lib/lib.d.ts","../node_modules/otherlib/index.d.ts","../node_modules/somelib/index.d.ts","../node_modules/lib1/index.d.ts","../node_modules/lib2/index.d.ts","./src/index.ts"],"fileInfos":[{"version":"eae9e83ef0f77eeb2e35dc9b91facce1-/// \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},"a40368814f37d4357a34c3f941f3e677-export type Str = string;","c83d508c75590e2f7051911d4a827ceb-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };","a508f6d5ab12f0c2168b5488ebbd34be-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };","528165de17b5f9f1dbbf984a062d9b57-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;","c367835e98822462afe5cacbac4d94c2-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };"],"fileIdsList":[[3],[2],[4,5]],"referencedMap":[[4,1],[5,1],[3,2],[6,3]]} +{"version":"FakeTSVersion","fileNames":["../src/tslibs/ts/lib/lib.d.ts","../node_modules/otherlib/index.d.ts","../node_modules/somelib/index.d.ts","../node_modules/lib1/index.d.ts","../node_modules/lib2/index.d.ts","./src/index.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},"1fe659ed0634bb57b6dc25e9062f1162-export type Str = string;","12e112ff6e2744bb42d8e0b511e44117-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };","b6305455d920a6729c435e6acf45eff6-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };","a5393e550a9c20a242a120bf6410db48-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;","42aef197ff5f079223e2c29fb2e77cc5-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };"],"fileIdsList":[[3],[2],[4,5]],"referencedMap":[[4,1],[5,1],[3,2],[6,3]]} //// [/home/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new* { "version": "FakeTSVersion", @@ -67,44 +67,44 @@ exports.foo2 = { foo: "b" }; "fileInfos": [ { "fileName": "../src/tslibs/ts/lib/lib.d.ts", - "version": "eae9e83ef0f77eeb2e35dc9b91facce1-/// \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": "eae9e83ef0f77eeb2e35dc9b91facce1-/// \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; };", + "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": "eae9e83ef0f77eeb2e35dc9b91facce1-/// \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; };", + "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": "../node_modules/otherlib/index.d.ts", - "version": "a40368814f37d4357a34c3f941f3e677-export type Str = string;", - "signature": "a40368814f37d4357a34c3f941f3e677-export type Str = string;", + "version": "1fe659ed0634bb57b6dc25e9062f1162-export type Str = string;", + "signature": "1fe659ed0634bb57b6dc25e9062f1162-export type Str = string;", "impliedNodeFormat": "CommonJS" }, { "fileName": "../node_modules/somelib/index.d.ts", - "version": "c83d508c75590e2f7051911d4a827ceb-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };", - "signature": "c83d508c75590e2f7051911d4a827ceb-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };", + "version": "12e112ff6e2744bb42d8e0b511e44117-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };", + "signature": "12e112ff6e2744bb42d8e0b511e44117-import type { Str } from 'otherLib';\nexport type Foo = { foo: Str; };", "impliedNodeFormat": "CommonJS" }, { "fileName": "../node_modules/lib1/index.d.ts", - "version": "a508f6d5ab12f0c2168b5488ebbd34be-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };", - "signature": "a508f6d5ab12f0c2168b5488ebbd34be-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };", + "version": "b6305455d920a6729c435e6acf45eff6-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };", + "signature": "b6305455d920a6729c435e6acf45eff6-import type { Foo } from 'someLib';\nexport type { Foo as Foo1 };", "impliedNodeFormat": "CommonJS" }, { "fileName": "../node_modules/lib2/index.d.ts", - "version": "528165de17b5f9f1dbbf984a062d9b57-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;", - "signature": "528165de17b5f9f1dbbf984a062d9b57-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;", + "version": "a5393e550a9c20a242a120bf6410db48-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;", + "signature": "a5393e550a9c20a242a120bf6410db48-import type { Foo } from 'somelib';\nexport type { Foo as Foo2 };\nexport declare const foo2: Foo;", "impliedNodeFormat": "CommonJS" }, { "fileName": "./src/index.ts", - "version": "c367835e98822462afe5cacbac4d94c2-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };", - "signature": "c367835e98822462afe5cacbac4d94c2-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };", + "version": "42aef197ff5f079223e2c29fb2e77cc5-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };", + "signature": "42aef197ff5f079223e2c29fb2e77cc5-import type { Foo1 } from 'lib1';\nimport type { Foo2 } from 'lib2';\nexport const foo1: Foo1 = { foo: \"a\" };\nexport const foo2: Foo2 = { foo: \"b\" };", "impliedNodeFormat": "CommonJS" } ], From 791c7a2f1544c6747d05d35eada594f476aa6b23 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Thu, 7 Aug 2025 14:39:12 -0700 Subject: [PATCH 3/3] use path in test baselining --- internal/execute/testsys_test.go | 10 +++++----- ...ile-incremental-with-case-insensitive-file-names.js | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/execute/testsys_test.go b/internal/execute/testsys_test.go index ea3cd10963..471b077776 100644 --- a/internal/execute/testsys_test.go +++ b/internal/execute/testsys_test.go @@ -185,10 +185,10 @@ func (s *testSys) baselineProgram(baseline *strings.Builder, program *incrementa for _, file := range program.GetProgram().GetSourceFiles() { if diagnostics, ok := testingData.SemanticDiagnosticsPerFile.Load(file.Path()); ok { if oldDiagnostics, ok := testingData.OldProgramSemanticDiagnosticsPerFile.Load(file.Path()); !ok || oldDiagnostics != diagnostics { - baseline.WriteString("*refresh* " + file.FileName() + "\n") + baseline.WriteString("*refresh* " + string(file.Path()) + "\n") } } else { - baseline.WriteString("*not cached* " + file.FileName() + "\n") + baseline.WriteString("*not cached* " + string(file.Path()) + "\n") } } @@ -198,11 +198,11 @@ func (s *testSys) baselineProgram(baseline *strings.Builder, program *incrementa if kind, ok := testingData.UpdatedSignatureKinds[file.Path()]; ok { switch kind { case incremental.SignatureUpdateKindComputedDts: - baseline.WriteString("(computed .d.ts) " + file.FileName() + "\n") + baseline.WriteString("(computed .d.ts) " + string(file.Path()) + "\n") case incremental.SignatureUpdateKindStoredAtEmit: - baseline.WriteString("(stored at emit) " + file.FileName() + "\n") + baseline.WriteString("(stored at emit) " + string(file.Path()) + "\n") case incremental.SignatureUpdateKindUsedVersion: - baseline.WriteString("(used version) " + file.FileName() + "\n") + baseline.WriteString("(used version) " + string(file.Path()) + "\n") } } } diff --git a/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js b/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js index 2f4f63b1bc..c748b3504d 100644 --- a/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js +++ b/testdata/baselines/reference/tsc/commandLine/Compile-incremental-with-case-insensitive-file-names.js @@ -162,8 +162,8 @@ interface Symbol { declare const console: { log(msg: any): void; }; SemanticDiagnostics:: -*refresh* /home/src/tslibs/TS/Lib/lib.d.ts -*refresh* /home/node_modules/otherLib/index.d.ts +*refresh* /home/src/tslibs/ts/lib/lib.d.ts +*refresh* /home/node_modules/otherlib/index.d.ts *refresh* /home/node_modules/somelib/index.d.ts *refresh* /home/node_modules/lib1/index.d.ts *refresh* /home/node_modules/lib2/index.d.ts