diff --git a/internal/compiler/fileloader.go b/internal/compiler/fileloader.go index 941cdd6728..9fbbc49057 100644 --- a/internal/compiler/fileloader.go +++ b/internal/compiler/fileloader.go @@ -254,6 +254,7 @@ func processAllProgramFiles( unsupportedExtensions: unsupportedExtensions, sourceFilesFoundSearchingNodeModules: sourceFilesFoundSearchingNodeModules, libFiles: libFilesMap, + missingFiles: missingFiles, includeProcessor: loader.includeProcessor, outputFileToProjectReferenceSource: outputFileToProjectReferenceSource, } diff --git a/internal/compiler/filesparser.go b/internal/compiler/filesparser.go index e4f35280da..d0fb499a67 100644 --- a/internal/compiler/filesparser.go +++ b/internal/compiler/filesparser.go @@ -240,16 +240,15 @@ func (w *filesParser) collect(loader *fileLoader, tasks []*parseTask, iterate fu func (w *filesParser) collectWorker(loader *fileLoader, tasks []*parseTask, iterate func(*parseTask), seen collections.Set[*parseTask]) { for _, task := range tasks { - if task.redirectedParseTask == nil { + // Exclude automatic type directive tasks from include reason processing, + // as these are internal implementation details and should not contribute + // to the reasons for including files. + if task.redirectedParseTask == nil && !task.isForAutomaticTypeDirective { includeReason := task.includeReason if task.loadedTask != nil { task = task.loadedTask } - if existing, ok := loader.includeProcessor.fileIncludeReasons[task.path]; ok { - loader.includeProcessor.fileIncludeReasons[task.path] = append(existing, includeReason) - } else { - loader.includeProcessor.fileIncludeReasons[task.path] = []*fileIncludeReason{includeReason} - } + w.addIncludeReason(loader, task, includeReason) } // ensure we only walk each task once if !task.loaded || !seen.AddIfAbsent(task) { @@ -267,3 +266,15 @@ func (w *filesParser) collectWorker(loader *fileLoader, tasks []*parseTask, iter iterate(task) } } + +func (w *filesParser) addIncludeReason(loader *fileLoader, task *parseTask, reason *fileIncludeReason) { + if task.redirectedParseTask != nil { + w.addIncludeReason(loader, task.redirectedParseTask, reason) + } else if task.loaded { + if existing, ok := loader.includeProcessor.fileIncludeReasons[task.path]; ok { + loader.includeProcessor.fileIncludeReasons[task.path] = append(existing, reason) + } else { + loader.includeProcessor.fileIncludeReasons[task.path] = []*fileIncludeReason{reason} + } + } +} diff --git a/internal/compiler/program.go b/internal/compiler/program.go index 096b87f048..d571f10257 100644 --- a/internal/compiler/program.go +++ b/internal/compiler/program.go @@ -1541,6 +1541,18 @@ func (p *Program) GetSourceFiles() []*ast.SourceFile { return p.files } +// Testing only +func (p *Program) GetIncludeReasons() map[tspath.Path][]*fileIncludeReason { + return p.includeProcessor.fileIncludeReasons +} + +// Testing only +func (p *Program) IsMissingPath(path tspath.Path) bool { + return slices.ContainsFunc(p.missingFiles, func(missingPath string) bool { + return p.toPath(missingPath) == path + }) +} + func (p *Program) ExplainFiles(w io.Writer) { toRelativeFileName := func(fileName string) string { return tspath.GetRelativePathFromDirectory(p.GetCurrentDirectory(), fileName, p.comparePathsOptions) diff --git a/internal/execute/tsctests/runner.go b/internal/execute/tsctests/runner.go index 6c5b8e4457..7cb8c261bd 100644 --- a/internal/execute/tsctests/runner.go +++ b/internal/execute/tsctests/runner.go @@ -80,8 +80,7 @@ func (test *tscInput) run(t *testing.T, scenario string) { sys.baselineFSwithDiff(baselineBuilder) result := test.executeCommand(sys, baselineBuilder, test.commandLineArgs) sys.serializeState(baselineBuilder) - sys.baselinePrograms(baselineBuilder) - var unexpectedDiff string + unexpectedDiff := sys.baselinePrograms(baselineBuilder, "Initial build") for index, do := range test.edits { sys.clearOutput() @@ -101,7 +100,7 @@ func (test *tscInput) run(t *testing.T, scenario string) { result.Watcher.DoCycle() } sys.serializeState(baselineBuilder) - sys.baselinePrograms(baselineBuilder) + unexpectedDiff += sys.baselinePrograms(baselineBuilder, fmt.Sprintf("Edit [%d]:: %s\n", index, do.caption)) }) wg.Queue(func() { // Compute build with all the edits diff --git a/internal/execute/tsctests/sys.go b/internal/execute/tsctests/sys.go index 9cf4b1ed99..199fce8e76 100644 --- a/internal/execute/tsctests/sys.go +++ b/internal/execute/tsctests/sys.go @@ -141,6 +141,7 @@ type snapshot struct { type testSys struct { currentWrite *strings.Builder programBaselines strings.Builder + programIncludeBaselines strings.Builder tracer *harnessutil.TracerForBaselining serializedDiff *snapshot forIncrementalCorrectness bool @@ -287,18 +288,23 @@ func (s *testSys) GetTrace(w io.Writer) func(str string) { } } -func (s *testSys) OnProgram(program *incremental.Program) { - if s.programBaselines.Len() != 0 { - s.programBaselines.WriteString("\n") +func (s *testSys) writeHeaderToBaseline(builder *strings.Builder, program *incremental.Program) { + if builder.Len() != 0 { + builder.WriteString("\n") } - testingData := program.GetTestingData() if configFilePath := program.Options().ConfigFilePath; configFilePath != "" { - s.programBaselines.WriteString(tspath.GetRelativePathFromDirectory(s.cwd, configFilePath, tspath.ComparePathsOptions{ + builder.WriteString(tspath.GetRelativePathFromDirectory(s.cwd, configFilePath, tspath.ComparePathsOptions{ UseCaseSensitiveFileNames: s.FS().UseCaseSensitiveFileNames(), CurrentDirectory: s.GetCurrentDirectory(), }) + "::\n") } +} + +func (s *testSys) OnProgram(program *incremental.Program) { + s.writeHeaderToBaseline(&s.programBaselines, program) + + testingData := program.GetTestingData() s.programBaselines.WriteString("SemanticDiagnostics::\n") for _, file := range program.GetProgram().GetSourceFiles() { if diagnostics, ok := testingData.SemanticDiagnosticsPerFile.Load(file.Path()); ok { @@ -324,11 +330,44 @@ func (s *testSys) OnProgram(program *incremental.Program) { } } } + + var filesWithoutIncludeReason []string + var fileNotInProgramWithIncludeReason []string + includeReasons := program.GetProgram().GetIncludeReasons() + for _, file := range program.GetProgram().GetSourceFiles() { + if _, ok := includeReasons[file.Path()]; !ok { + filesWithoutIncludeReason = append(filesWithoutIncludeReason, string(file.Path())) + } + } + for path := range includeReasons { + if program.GetProgram().GetSourceFileByPath(path) == nil && !program.GetProgram().IsMissingPath(path) { + fileNotInProgramWithIncludeReason = append(fileNotInProgramWithIncludeReason, string(path)) + } + } + if len(filesWithoutIncludeReason) > 0 || len(fileNotInProgramWithIncludeReason) > 0 { + s.writeHeaderToBaseline(&s.programIncludeBaselines, program) + s.programIncludeBaselines.WriteString("!!! Expected all files to have include reasons\nfilesWithoutIncludeReason::\n") + for _, file := range filesWithoutIncludeReason { + s.programIncludeBaselines.WriteString(" " + file + "\n") + } + s.programIncludeBaselines.WriteString("filesNotInProgramWithIncludeReason::\n") + for _, file := range fileNotInProgramWithIncludeReason { + s.programIncludeBaselines.WriteString(" " + file + "\n") + } + } } -func (s *testSys) baselinePrograms(baseline *strings.Builder) { +func (s *testSys) baselinePrograms(baseline *strings.Builder, header string) string { baseline.WriteString(s.programBaselines.String()) s.programBaselines.Reset() + var result string + if s.programIncludeBaselines.Len() > 0 { + result += fmt.Sprintf("\n\n%s\n!!! Include reasons expectations don't match pls review!!!\n", header) + result += s.programIncludeBaselines.String() + s.programIncludeBaselines.Reset() + baseline.WriteString(result) + } + return result } func (s *testSys) serializeState(baseline *strings.Builder) { diff --git a/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js b/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js index 490ebbdb4b..8925e1504a 100644 --- a/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js +++ b/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js @@ -88,6 +88,7 @@ projects/shared/dist/src/logging.d.ts File is output of project reference source 'projects/shared/src/logging.ts' projects/shared/dist/src/myClass.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' File is output of project reference source 'projects/shared/src/myClass.ts' projects/shared/dist/src/random.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' @@ -426,6 +427,7 @@ projects/shared/dist/src/logging.d.ts File is output of project reference source 'projects/shared/src/logging.ts' projects/shared/dist/src/myClass.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' File is output of project reference source 'projects/shared/src/myClass.ts' projects/shared/dist/src/random.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' @@ -699,6 +701,7 @@ projects/shared/dist/src/logging.d.ts File is output of project reference source 'projects/shared/src/logging.ts' projects/shared/dist/src/myClass.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts Matched by include pattern 'src/**/*.ts' in 'projects/server/tsconfig.json' diff --git a/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project.js b/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project.js index 3286e84fd3..fba2e0b30f 100644 --- a/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project.js +++ b/testdata/baselines/reference/tsbuild/roots/when-root-file-is-from-referenced-project.js @@ -84,6 +84,7 @@ File '/home/src/workspaces/solution/projects/shared/src/myClass.ts' exists - use ../../tslibs/TS/Lib/lib.d.ts Default library for target 'ES5' projects/shared/dist/src/myClass.d.ts + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts @@ -422,6 +423,7 @@ File '/home/src/workspaces/solution/projects/shared/src/myClass.ts' exists - use ../../tslibs/TS/Lib/lib.d.ts Default library for target 'ES5' projects/shared/dist/src/myClass.d.ts + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts @@ -695,6 +697,7 @@ File '/home/src/workspaces/solution/projects/shared/src/myClass.ts' exists - use ../../tslibs/TS/Lib/lib.d.ts Default library for target 'ES5' projects/shared/dist/src/myClass.d.ts + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts diff --git a/testdata/baselines/reference/tsbuild/sample/explainFiles.js b/testdata/baselines/reference/tsbuild/sample/explainFiles.js index fa3112b13d..34f858c988 100644 --- a/testdata/baselines/reference/tsbuild/sample/explainFiles.js +++ b/testdata/baselines/reference/tsbuild/sample/explainFiles.js @@ -104,6 +104,7 @@ core/index.d.ts Imported via '../core/index' from file 'tests/index.ts' File is output of project reference source 'core/index.ts' core/anotherModule.d.ts + Imported via '../core/anotherModule' from file 'logic/index.d.ts' Imported via '../core/anotherModule' from file 'tests/index.ts' File is output of project reference source 'core/anotherModule.ts' logic/index.d.ts @@ -527,6 +528,7 @@ core/index.d.ts Imported via '../core/index' from file 'tests/index.ts' File is output of project reference source 'core/index.ts' core/anotherModule.d.ts + Imported via '../core/anotherModule' from file 'logic/index.d.ts' Imported via '../core/anotherModule' from file 'tests/index.ts' File is output of project reference source 'core/anotherModule.ts' logic/index.d.ts diff --git a/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js b/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js index 3c26c1fb21..b3643a328a 100644 --- a/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js +++ b/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project-and-shared-is-first.js @@ -90,6 +90,7 @@ projects/shared/dist/src/logging.d.ts File is output of project reference source 'projects/shared/src/logging.ts' projects/shared/dist/src/myClass.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' File is output of project reference source 'projects/shared/src/myClass.ts' projects/shared/dist/src/random.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' @@ -422,6 +423,7 @@ projects/shared/dist/src/logging.d.ts File is output of project reference source 'projects/shared/src/logging.ts' projects/shared/dist/src/myClass.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' File is output of project reference source 'projects/shared/src/myClass.ts' projects/shared/dist/src/random.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' @@ -689,6 +691,7 @@ projects/shared/dist/src/logging.d.ts File is output of project reference source 'projects/shared/src/logging.ts' projects/shared/dist/src/myClass.d.ts Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts Matched by include pattern 'src/**/*.ts' in 'projects/server/tsconfig.json' diff --git a/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project.js b/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project.js index 22b038f81c..48f204da2b 100644 --- a/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project.js +++ b/testdata/baselines/reference/tsbuildWatch/roots/when-root-file-is-from-referenced-project.js @@ -86,6 +86,7 @@ File '/home/src/workspaces/solution/projects/shared/src/myClass.ts' exists - use ../../tslibs/TS/Lib/lib.d.ts Default library for target 'ES5' projects/shared/dist/src/myClass.d.ts + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts @@ -418,6 +419,7 @@ File '/home/src/workspaces/solution/projects/shared/src/myClass.ts' exists - use ../../tslibs/TS/Lib/lib.d.ts Default library for target 'ES5' projects/shared/dist/src/myClass.d.ts + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts @@ -685,6 +687,7 @@ File '/home/src/workspaces/solution/projects/shared/src/myClass.ts' exists - use ../../tslibs/TS/Lib/lib.d.ts Default library for target 'ES5' projects/shared/dist/src/myClass.d.ts + Imported via ':shared/myClass.js' from file 'projects/server/src/server.ts' Matched by include pattern '../shared/src/**/*.ts' in 'projects/server/tsconfig.json' File is output of project reference source 'projects/shared/src/myClass.ts' projects/server/src/server.ts