diff --git a/internal/ast/ast.go b/internal/ast/ast.go
index 87e9c79c53..831fb1b378 100644
--- a/internal/ast/ast.go
+++ b/internal/ast/ast.go
@@ -10374,10 +10374,6 @@ func (node *SourceFile) Path() tspath.Path {
return node.parseOptions.Path
}
-func (node *SourceFile) OriginalFileName() string {
- return node.FileName() // !!! redirect source files
-}
-
func (node *SourceFile) Imports() []*LiteralLikeNode {
return node.imports
}
diff --git a/internal/compiler/emitHost.go b/internal/compiler/emitHost.go
index b2eeed388f..cf6f68dee6 100644
--- a/internal/compiler/emitHost.go
+++ b/internal/compiler/emitHost.go
@@ -74,6 +74,10 @@ func (host *emitHost) GetPackageJsonInfo(pkgJsonPath string) modulespecifiers.Pa
return host.program.GetPackageJsonInfo(pkgJsonPath)
}
+func (host *emitHost) GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFileName) string {
+ return host.program.GetSourceOfProjectReferenceIfOutputIncluded(file)
+}
+
func (host *emitHost) GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
return host.program.GetOutputAndProjectReference(path)
}
diff --git a/internal/compiler/fileInclude.go b/internal/compiler/fileInclude.go
new file mode 100644
index 0000000000..2e16f018df
--- /dev/null
+++ b/internal/compiler/fileInclude.go
@@ -0,0 +1,336 @@
+package compiler
+
+import (
+ "fmt"
+ "sync"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/diagnostics"
+ "github.com/microsoft/typescript-go/internal/module"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+type fileIncludeKind int
+
+const (
+ // References from file
+ fileIncludeKindImport = iota
+ fileIncludeKindReferenceFile
+ fileIncludeKindTypeReferenceDirective
+ fileIncludeKindLibReferenceDirective
+
+ fileIncludeKindRootFile
+ fileIncludeKindSourceFromProjectReference
+ fileIncludeKindOutputFromProjectReference
+ fileIncludeKindLibFile
+ fileIncludeKindAutomaticTypeDirectiveFile
+)
+
+type fileIncludeReason struct {
+ kind fileIncludeKind
+ data any
+
+ // Uses relative file name
+ relativeFileNameDiag *ast.Diagnostic
+ relativeFileNameDiagOnce sync.Once
+
+ // Uses file name as is
+ diag *ast.Diagnostic
+ diagOnce sync.Once
+}
+
+type referencedFileData struct {
+ file tspath.Path
+ index int
+ synthetic *ast.Node
+}
+
+type referenceFileLocation struct {
+ file *ast.SourceFile
+ node *ast.Node
+ ref *ast.FileReference
+ packageId module.PackageId
+ isSynthetic bool
+}
+
+func (r *referenceFileLocation) text() string {
+ if r.node != nil {
+ return r.node.Text()
+ } else {
+ return r.file.Text()[r.ref.Pos():r.ref.End()]
+ }
+}
+
+func (r *referenceFileLocation) diagnosticAt(message *diagnostics.Message, args ...any) *ast.Diagnostic {
+ if r.node != nil {
+ return tsoptions.CreateDiagnosticForNodeInSourceFile(r.file, r.node, message, args...)
+ } else {
+ return ast.NewDiagnostic(r.file, r.ref.TextRange, message, args...)
+ }
+}
+
+type automaticTypeDirectiveFileData struct {
+ typeReference string
+ packageId module.PackageId
+}
+
+func (r *fileIncludeReason) asIndex() int {
+ return r.data.(int)
+}
+
+func (r *fileIncludeReason) asLibFileIndex() (int, bool) {
+ index, ok := r.data.(int)
+ return index, ok
+}
+
+func (r *fileIncludeReason) isReferencedFile() bool {
+ return r != nil && r.kind <= fileIncludeKindLibReferenceDirective
+}
+
+func (r *fileIncludeReason) asReferencedFileData() *referencedFileData {
+ return r.data.(*referencedFileData)
+}
+
+func (r *fileIncludeReason) asAutomaticTypeDirectiveFileData() *automaticTypeDirectiveFileData {
+ return r.data.(*automaticTypeDirectiveFileData)
+}
+
+func (r *fileIncludeReason) getReferencedLocation(program *Program) *referenceFileLocation {
+ ref := r.asReferencedFileData()
+ file := program.GetSourceFileByPath(ref.file)
+ switch r.kind {
+ case fileIncludeKindImport:
+ var specifier *ast.Node
+ var isSynthetic bool
+ if ref.synthetic != nil {
+ specifier = ref.synthetic
+ isSynthetic = true
+ } else if ref.index < len(file.Imports()) {
+ specifier = file.Imports()[ref.index]
+ } else {
+ augIndex := len(file.Imports())
+ for _, imp := range file.ModuleAugmentations {
+ if imp.Kind == ast.KindStringLiteral {
+ if augIndex == ref.index {
+ specifier = imp
+ break
+ }
+ augIndex++
+ }
+ }
+ }
+ resolution := program.GetResolvedModuleFromModuleSpecifier(file, specifier)
+ return &referenceFileLocation{
+ file: file,
+ node: specifier,
+ packageId: resolution.PackageId,
+ isSynthetic: isSynthetic,
+ }
+ case fileIncludeKindReferenceFile:
+ return &referenceFileLocation{
+ file: file,
+ ref: file.ReferencedFiles[ref.index],
+ }
+ case fileIncludeKindTypeReferenceDirective:
+ return &referenceFileLocation{
+ file: file,
+ ref: file.TypeReferenceDirectives[ref.index],
+ }
+ case fileIncludeKindLibReferenceDirective:
+ return &referenceFileLocation{
+ file: file,
+ ref: file.LibReferenceDirectives[ref.index],
+ }
+ default:
+ panic(fmt.Sprintf("unknown reason: %v", r.kind))
+ }
+}
+
+func (r *fileIncludeReason) toDiagnostic(program *Program, relativeFileName bool) *ast.Diagnostic {
+ if relativeFileName {
+ r.relativeFileNameDiagOnce.Do(func() {
+ r.relativeFileNameDiag = r.computeDiagnostic(program, func(fileName string) string {
+ return tspath.GetRelativePathFromDirectory(program.GetCurrentDirectory(), fileName, program.comparePathsOptions)
+ })
+ })
+ return r.relativeFileNameDiag
+ } else {
+ r.diagOnce.Do(func() {
+ r.diag = r.computeDiagnostic(program, func(fileName string) string { return fileName })
+ })
+ return r.diag
+ }
+}
+
+func (r *fileIncludeReason) computeDiagnostic(program *Program, toFileName func(string) string) *ast.Diagnostic {
+ if r.isReferencedFile() {
+ return r.computeReferenceFileDiagnostic(program, toFileName)
+ }
+ switch r.kind {
+ case fileIncludeKindRootFile:
+ if program.opts.Config.ConfigFile != nil {
+ config := program.opts.Config
+ fileName := tspath.GetNormalizedAbsolutePath(config.FileNames()[r.asIndex()], program.GetCurrentDirectory())
+ if matchedFileSpec := config.GetMatchedFileSpec(fileName); matchedFileSpec != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Part_of_files_list_in_tsconfig_json, matchedFileSpec, toFileName(fileName))
+ } else if matchedIncludeSpec, isDefaultIncludeSpec := config.GetMatchedIncludeSpec(fileName); matchedIncludeSpec != "" {
+ if isDefaultIncludeSpec {
+ return ast.NewCompilerDiagnostic(diagnostics.Matched_by_default_include_pattern_Asterisk_Asterisk_Slash_Asterisk)
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Matched_by_include_pattern_0_in_1, matchedIncludeSpec, toFileName(config.ConfigName()))
+ }
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Root_file_specified_for_compilation)
+ }
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Root_file_specified_for_compilation)
+ }
+ case fileIncludeKindSourceFromProjectReference,
+ fileIncludeKindOutputFromProjectReference:
+ diag := core.IfElse(
+ r.kind == fileIncludeKindOutputFromProjectReference,
+ diagnostics.Output_from_referenced_project_0_included_because_module_is_specified_as_none,
+ diagnostics.Source_from_referenced_project_0_included_because_module_is_specified_as_none,
+ )
+ referencedResolvedRef := program.projectReferenceFileMapper.getResolvedProjectReferences()[r.asIndex()]
+ return ast.NewCompilerDiagnostic(diag, toFileName(referencedResolvedRef.ConfigName()))
+ case fileIncludeKindAutomaticTypeDirectiveFile:
+ data := r.asAutomaticTypeDirectiveFileData()
+ if program.Options().Types != nil {
+ if data.packageId.Name != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Entry_point_of_type_library_0_specified_in_compilerOptions_with_packageId_1, data.typeReference, data.packageId.String())
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Entry_point_of_type_library_0_specified_in_compilerOptions, data.typeReference)
+ }
+ } else {
+ if data.packageId.Name != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Entry_point_for_implicit_type_library_0_with_packageId_1, data.typeReference, data.packageId.String())
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Entry_point_for_implicit_type_library_0, data.typeReference)
+ }
+ }
+ case fileIncludeKindLibFile:
+ if index, ok := r.asLibFileIndex(); ok {
+ return ast.NewCompilerDiagnostic(diagnostics.Library_0_specified_in_compilerOptions, program.Options().Lib[index])
+ } else if target := program.Options().GetEmitScriptTarget().String(); target != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Default_library_for_target_0, target)
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Default_library)
+ }
+ default:
+ panic(fmt.Sprintf("unknown reason: %v", r.kind))
+ }
+}
+
+func (r *fileIncludeReason) computeReferenceFileDiagnostic(program *Program, toFileName func(string) string) *ast.Diagnostic {
+ referenceLocation := program.includeProcessor.getReferenceLocation(r, program)
+ referenceText := referenceLocation.text()
+ switch r.kind {
+ case fileIncludeKindImport:
+ if !referenceLocation.isSynthetic {
+ if referenceLocation.packageId.Name != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Imported_via_0_from_file_1_with_packageId_2, referenceText, toFileName(referenceLocation.file.FileName()), referenceLocation.packageId.String())
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Imported_via_0_from_file_1, referenceText, toFileName(referenceLocation.file.FileName()))
+ }
+ } else if specifier, ok := program.importHelpersImportSpecifiers[referenceLocation.file.Path()]; ok && specifier == referenceLocation.node {
+ if referenceLocation.packageId.Name != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Imported_via_0_from_file_1_with_packageId_2_to_import_importHelpers_as_specified_in_compilerOptions, referenceText, toFileName(referenceLocation.file.FileName()), referenceLocation.packageId.String())
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Imported_via_0_from_file_1_to_import_importHelpers_as_specified_in_compilerOptions, referenceText, toFileName(referenceLocation.file.FileName()))
+ }
+ } else {
+ if referenceLocation.packageId.Name != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Imported_via_0_from_file_1_with_packageId_2_to_import_jsx_and_jsxs_factory_functions, referenceText, toFileName(referenceLocation.file.FileName()), referenceLocation.packageId.String())
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Imported_via_0_from_file_1_to_import_jsx_and_jsxs_factory_functions, referenceText, toFileName(referenceLocation.file.FileName()))
+ }
+ }
+ case fileIncludeKindReferenceFile:
+ return ast.NewCompilerDiagnostic(diagnostics.Referenced_via_0_from_file_1, referenceText, toFileName(referenceLocation.file.FileName()))
+ case fileIncludeKindTypeReferenceDirective:
+ if referenceLocation.packageId.Name != "" {
+ return ast.NewCompilerDiagnostic(diagnostics.Type_library_referenced_via_0_from_file_1_with_packageId_2, referenceText, toFileName(referenceLocation.file.FileName()), referenceLocation.packageId.String())
+ } else {
+ return ast.NewCompilerDiagnostic(diagnostics.Type_library_referenced_via_0_from_file_1, referenceText, toFileName(referenceLocation.file.FileName()))
+ }
+ case fileIncludeKindLibReferenceDirective:
+ return ast.NewCompilerDiagnostic(diagnostics.Library_referenced_via_0_from_file_1, referenceText, toFileName(referenceLocation.file.FileName()))
+ default:
+ panic(fmt.Sprintf("unknown reason: %v", r.kind))
+ }
+}
+
+func (r *fileIncludeReason) toRelatedInfo(program *Program) *ast.Diagnostic {
+ if r.isReferencedFile() {
+ return r.computeReferenceFileRelatedInfo(program)
+ }
+ if program.opts.Config.ConfigFile == nil {
+ return nil
+ }
+ config := program.opts.Config
+ switch r.kind {
+ case fileIncludeKindRootFile:
+ fileName := tspath.GetNormalizedAbsolutePath(config.FileNames()[r.asIndex()], program.GetCurrentDirectory())
+ if matchedFileSpec := config.GetMatchedFileSpec(fileName); matchedFileSpec != "" {
+ if filesNode := tsoptions.GetTsConfigPropArrayElementValue(config.ConfigFile.SourceFile, "files", matchedFileSpec); filesNode != nil {
+ return tsoptions.CreateDiagnosticForNodeInSourceFile(config.ConfigFile.SourceFile, filesNode.AsNode(), diagnostics.File_is_matched_by_files_list_specified_here)
+ }
+ } else if matchedIncludeSpec, isDefaultIncludeSpec := config.GetMatchedIncludeSpec(fileName); matchedIncludeSpec != "" && !isDefaultIncludeSpec {
+ if includeNode := tsoptions.GetTsConfigPropArrayElementValue(config.ConfigFile.SourceFile, "include", matchedIncludeSpec); includeNode != nil {
+ return tsoptions.CreateDiagnosticForNodeInSourceFile(config.ConfigFile.SourceFile, includeNode.AsNode(), diagnostics.File_is_matched_by_include_pattern_specified_here)
+ }
+ }
+ case fileIncludeKindSourceFromProjectReference,
+ fileIncludeKindOutputFromProjectReference:
+ return tsoptions.CreateDiagnosticAtReferenceSyntax(
+ config,
+ r.asIndex(),
+ core.IfElse(
+ r.kind == fileIncludeKindOutputFromProjectReference,
+ diagnostics.File_is_output_from_referenced_project_specified_here,
+ diagnostics.File_is_source_from_referenced_project_specified_here,
+ ))
+ case fileIncludeKindAutomaticTypeDirectiveFile:
+ if program.Options().Types != nil {
+ data := r.asAutomaticTypeDirectiveFileData()
+ if typesSyntax := tsoptions.GetOptionsSyntaxByArrayElementValue(program.includeProcessor.getCompilerOptionsObjectLiteralSyntax(program), "types", data.typeReference); typesSyntax != nil {
+ return tsoptions.CreateDiagnosticForNodeInSourceFile(config.ConfigFile.SourceFile, typesSyntax.AsNode(), diagnostics.File_is_entry_point_of_type_library_specified_here)
+ }
+ }
+ case fileIncludeKindLibFile:
+ if index, ok := r.asLibFileIndex(); ok {
+ if libSyntax := tsoptions.GetOptionsSyntaxByArrayElementValue(program.includeProcessor.getCompilerOptionsObjectLiteralSyntax(program), "lib", program.Options().Lib[index]); libSyntax != nil {
+ return tsoptions.CreateDiagnosticForNodeInSourceFile(config.ConfigFile.SourceFile, libSyntax.AsNode(), diagnostics.File_is_library_specified_here)
+ }
+ } else if target := program.Options().GetEmitScriptTarget().String(); target != "" {
+ if targetValueSyntax := tsoptions.ForEachPropertyAssignment(program.includeProcessor.getCompilerOptionsObjectLiteralSyntax(program), "target", tsoptions.GetCallbackForFindingPropertyAssignmentByValue(target)); targetValueSyntax != nil {
+ return tsoptions.CreateDiagnosticForNodeInSourceFile(config.ConfigFile.SourceFile, targetValueSyntax.AsNode(), diagnostics.File_is_default_library_for_target_specified_here)
+ }
+ }
+ default:
+ panic(fmt.Sprintf("unknown reason: %v", r.kind))
+ }
+ return nil
+}
+
+func (r *fileIncludeReason) computeReferenceFileRelatedInfo(program *Program) *ast.Diagnostic {
+ referenceLocation := program.includeProcessor.getReferenceLocation(r, program)
+ if referenceLocation.isSynthetic {
+ return nil
+ }
+ switch r.kind {
+ case fileIncludeKindImport:
+ return referenceLocation.diagnosticAt(diagnostics.File_is_included_via_import_here)
+ case fileIncludeKindReferenceFile:
+ return referenceLocation.diagnosticAt(diagnostics.File_is_included_via_reference_here)
+ case fileIncludeKindTypeReferenceDirective:
+ return referenceLocation.diagnosticAt(diagnostics.File_is_included_via_type_library_reference_here)
+ case fileIncludeKindLibReferenceDirective:
+ return referenceLocation.diagnosticAt(diagnostics.File_is_included_via_library_reference_here)
+ default:
+ panic(fmt.Sprintf("unknown reason: %v", r.kind))
+ }
+}
diff --git a/internal/compiler/fileloader.go b/internal/compiler/fileloader.go
index c6a5aab71b..1df4c404ec 100644
--- a/internal/compiler/fileloader.go
+++ b/internal/compiler/fileloader.go
@@ -34,8 +34,9 @@ type fileLoader struct {
comparePathsOptions tspath.ComparePathsOptions
supportedExtensions []string
- filesParser *filesParser
- rootTasks []*parseTask
+ filesParser *filesParser
+ rootTasks []*parseTask
+ includeProcessor *includeProcessor
totalFileCount atomic.Int32
libFileCount atomic.Int32
@@ -65,7 +66,10 @@ type processedFiles struct {
// List of present unsupported extensions
unsupportedExtensions []string
sourceFilesFoundSearchingNodeModules collections.Set[tspath.Path]
- fileLoadDiagnostics *ast.DiagnosticsCollection
+ includeProcessor *includeProcessor
+ // if file was included using source file and its output is actually part of program
+ // this contains mapping from output to source file
+ outputFileToProjectReferenceSource map[tspath.Path]string
}
type jsxRuntimeImportSpecifier struct {
@@ -97,24 +101,24 @@ func processAllProgramFiles(
},
rootTasks: make([]*parseTask, 0, len(rootFiles)+len(compilerOptions.Lib)),
supportedExtensions: core.Flatten(tsoptions.GetSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, supportedExtensions)),
+ includeProcessor: &includeProcessor{},
}
loader.addProjectReferenceTasks(singleThreaded)
loader.resolver = module.NewResolver(loader.projectReferenceFileMapper.host, compilerOptions, opts.TypingsLocation, opts.ProjectName)
-
- for _, file := range rootFiles {
- loader.addRootTask(file, nil)
+ for index, rootFile := range rootFiles {
+ loader.addRootTask(rootFile, nil, &fileIncludeReason{kind: fileIncludeKindRootFile, data: index})
}
-
if len(rootFiles) > 0 && compilerOptions.NoLib.IsFalseOrUnknown() {
if compilerOptions.Lib == nil {
name := tsoptions.GetDefaultLibFileName(compilerOptions)
libFile := loader.pathForLibFile(name)
- loader.addRootTask(libFile.path, libFile)
+ loader.addRootTask(libFile.path, libFile, &fileIncludeReason{kind: fileIncludeKindLibFile})
+
} else {
- for _, lib := range compilerOptions.Lib {
+ for index, lib := range compilerOptions.Lib {
if name, ok := tsoptions.GetLibFileName(lib); ok {
libFile := loader.pathForLibFile(name)
- loader.addRootTask(libFile.path, libFile)
+ loader.addRootTask(libFile.path, libFile, &fileIncludeReason{kind: fileIncludeKindLibFile, data: index})
}
// !!! error on unknown name
}
@@ -138,6 +142,8 @@ func processAllProgramFiles(
libFiles := make([]*ast.SourceFile, 0, totalFileCount) // totalFileCount here since we append files to it later to construct the final list
filesByPath := make(map[tspath.Path]*ast.SourceFile, totalFileCount)
+ loader.includeProcessor.fileIncludeReasons = make(map[tspath.Path][]*fileIncludeReason, totalFileCount)
+ outputFileToProjectReferenceSource := make(map[tspath.Path]string, totalFileCount)
resolvedModules := make(map[tspath.Path]module.ModeAwareCache[*module.ResolvedModule], totalFileCount+1)
typeResolutionsInFile := make(map[tspath.Path]module.ModeAwareCache[*module.ResolvedTypeReferenceDirective], totalFileCount)
sourceFileMetaDatas := make(map[tspath.Path]ast.SourceFileMetaData, totalFileCount)
@@ -146,10 +152,12 @@ func processAllProgramFiles(
var unsupportedExtensions []string
var sourceFilesFoundSearchingNodeModules collections.Set[tspath.Path]
libFilesMap := make(map[tspath.Path]*LibFile, libFileCount)
- fileLoadDiagnostics := &ast.DiagnosticsCollection{}
loader.filesParser.collect(&loader, loader.rootTasks, func(task *parseTask) {
- if task.isRedirected {
+ if task.redirectedParseTask != nil {
+ if !opts.canUseProjectReferenceSource() {
+ outputFileToProjectReferenceSource[task.redirectedParseTask.path] = task.FileName()
+ }
return
}
@@ -160,16 +168,35 @@ func processAllProgramFiles(
file := task.file
path := task.path
if file == nil {
+ // !!! sheetal file preprocessing diagnostic explaining getSourceFileFromReferenceWorker
missingFiles = append(missingFiles, task.normalizedFilePath)
return
}
+
+ // !!! sheetal todo porting file case errors
+ // if _, ok := filesByPath[path]; ok {
+ // Check if it differs only in drive letters its ok to ignore that error:
+ // const checkedAbsolutePath = getNormalizedAbsolutePathWithoutRoot(checkedName, currentDirectory);
+ // const inputAbsolutePath = getNormalizedAbsolutePathWithoutRoot(fileName, currentDirectory);
+ // if (checkedAbsolutePath !== inputAbsolutePath) {
+ // reportFileNamesDifferOnlyInCasingError(fileName, file, reason);
+ // }
+ // } else if loader.comparePathsOptions.UseCaseSensitiveFileNames {
+ // pathIgnoreCase := tspath.ToPath(file.FileName(), loader.comparePathsOptions.CurrentDirectory, false)
+ // // for case-sensitsive file systems check if we've already seen some file with similar filename ignoring case
+ // if _, ok := filesByNameIgnoreCase[pathIgnoreCase]; ok {
+ // reportFileNamesDifferOnlyInCasingError(fileName, existingFile, reason);
+ // } else {
+ // filesByNameIgnoreCase[pathIgnoreCase] = file
+ // }
+ // }
+
if task.libFile != nil {
libFiles = append(libFiles, file)
libFilesMap[path] = task.libFile
} else {
files = append(files, file)
}
-
filesByPath[path] = file
resolvedModules[path] = task.resolutionsInFile
typeResolutionsInFile[path] = task.typeResolutionsInFile
@@ -199,21 +226,6 @@ func processAllProgramFiles(
allFiles := append(libFiles, files...)
- for _, resolutions := range resolvedModules {
- for _, resolvedModule := range resolutions {
- for _, diag := range resolvedModule.ResolutionDiagnostics {
- fileLoadDiagnostics.Add(diag)
- }
- }
- }
- for _, typeResolutions := range typeResolutionsInFile {
- for _, resolvedTypeRef := range typeResolutions {
- for _, diag := range resolvedTypeRef.ResolutionDiagnostics {
- fileLoadDiagnostics.Add(diag)
- }
- }
- }
-
keys := slices.Collect(loader.pathForLibFileResolutions.Keys())
slices.Sort(keys)
for _, key := range keys {
@@ -224,9 +236,6 @@ func processAllProgramFiles(
for _, trace := range value.trace {
opts.Host.Trace(trace)
}
- for _, diag := range value.resolution.ResolutionDiagnostics {
- fileLoadDiagnostics.Add(diag)
- }
}
return processedFiles{
@@ -242,7 +251,8 @@ func processAllProgramFiles(
unsupportedExtensions: unsupportedExtensions,
sourceFilesFoundSearchingNodeModules: sourceFilesFoundSearchingNodeModules,
libFiles: libFilesMap,
- fileLoadDiagnostics: fileLoadDiagnostics,
+ includeProcessor: loader.includeProcessor,
+ outputFileToProjectReferenceSource: outputFileToProjectReferenceSource,
}
}
@@ -250,10 +260,14 @@ func (p *fileLoader) toPath(file string) tspath.Path {
return tspath.ToPath(file, p.opts.Host.GetCurrentDirectory(), p.opts.Host.FS().UseCaseSensitiveFileNames())
}
-func (p *fileLoader) addRootTask(fileName string, libFile *LibFile) {
+func (p *fileLoader) addRootTask(fileName string, libFile *LibFile, includeReason *fileIncludeReason) {
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, libFile: libFile, root: true})
+ p.rootTasks = append(p.rootTasks, &parseTask{
+ normalizedFilePath: absPath,
+ libFile: libFile,
+ includeReason: includeReason,
+ })
}
}
@@ -266,7 +280,10 @@ func (p *fileLoader) addAutomaticTypeDirectiveTasks() {
containingDirectory = p.opts.Host.GetCurrentDirectory()
}
containingFileName := tspath.CombinePaths(containingDirectory, module.InferredTypesContainingFile)
- p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: containingFileName, isForAutomaticTypeDirective: true})
+ p.rootTasks = append(p.rootTasks, &parseTask{
+ normalizedFilePath: containingFileName,
+ isForAutomaticTypeDirective: true,
+ })
}
func (p *fileLoader) resolveAutomaticTypeDirectives(containingFileName string) (
@@ -288,6 +305,10 @@ func (p *fileLoader) resolveAutomaticTypeDirectives(containingFileName string) (
fileName: resolved.ResolvedFileName,
increaseDepth: resolved.IsExternalLibraryImport,
elideOnDepth: false,
+ includeReason: &fileIncludeReason{
+ kind: fileIncludeKindAutomaticTypeDirectiveFile,
+ data: &automaticTypeDirectiveFileData{name, resolved.PackageId},
+ },
})
}
}
@@ -317,18 +338,30 @@ func (p *fileLoader) addProjectReferenceTasks(singleThreaded bool) {
// when no module system is specified, allowing including all files for global symbol merging
// !!! sheetal Do we really need it?
if len(p.opts.Config.FileNames()) != 0 {
- for _, resolved := range p.projectReferenceFileMapper.getResolvedProjectReferences() {
+ for index, resolved := range p.projectReferenceFileMapper.getResolvedProjectReferences() {
if resolved == nil || resolved.CompilerOptions().GetEmitModuleKind() != core.ModuleKindNone {
continue
}
if p.opts.canUseProjectReferenceSource() {
for _, fileName := range resolved.FileNames() {
- p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: fileName})
+ p.rootTasks = append(p.rootTasks, &parseTask{
+ normalizedFilePath: fileName,
+ includeReason: &fileIncludeReason{
+ kind: fileIncludeKindSourceFromProjectReference,
+ data: index,
+ },
+ })
}
} else {
for outputDts := range resolved.GetOutputDeclarationFileNames() {
if outputDts != "" {
- p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: outputDts})
+ p.rootTasks = append(p.rootTasks, &parseTask{
+ normalizedFilePath: outputDts,
+ includeReason: &fileIncludeReason{
+ kind: fileIncludeKindOutputFromProjectReference,
+ data: index,
+ },
+ })
}
}
}
@@ -392,7 +425,7 @@ func (p *fileLoader) parseSourceFile(t *parseTask) *ast.SourceFile {
return sourceFile
}
-func (p *fileLoader) resolveTripleslashPathReference(moduleName string, containingFile string) resolvedRef {
+func (p *fileLoader) resolveTripleslashPathReference(moduleName string, containingFile string, index int) resolvedRef {
basePath := tspath.GetDirectoryPath(containingFile)
referencedFileName := moduleName
@@ -401,6 +434,13 @@ func (p *fileLoader) resolveTripleslashPathReference(moduleName string, containi
}
return resolvedRef{
fileName: tspath.NormalizePath(referencedFileName),
+ includeReason: &fileIncludeReason{
+ kind: fileIncludeKindReferenceFile,
+ data: &referencedFileData{
+ file: p.toPath(containingFile),
+ index: index,
+ },
+ },
}
}
@@ -413,11 +453,18 @@ func (p *fileLoader) resolveTypeReferenceDirectives(t *parseTask) {
typeResolutionsInFile := make(module.ModeAwareCache[*module.ResolvedTypeReferenceDirective], len(file.TypeReferenceDirectives))
var typeResolutionsTrace []string
- for _, ref := range file.TypeReferenceDirectives {
+ for index, ref := range file.TypeReferenceDirectives {
redirect := p.projectReferenceFileMapper.getRedirectForResolution(file)
resolutionMode := getModeForTypeReferenceDirectiveInFile(ref, file, meta, module.GetCompilerOptionsWithRedirect(p.opts.Config.CompilerOptions(), redirect))
resolved, trace := p.resolver.ResolveTypeReferenceDirective(ref.FileName, file.FileName(), resolutionMode, redirect)
typeResolutionsInFile[module.ModeAwareCacheKey{Name: ref.FileName, Mode: resolutionMode}] = resolved
+ includeReason := &fileIncludeReason{
+ kind: fileIncludeKindTypeReferenceDirective,
+ data: &referencedFileData{
+ file: t.path,
+ index: index,
+ },
+ }
typeResolutionsTrace = append(typeResolutionsTrace, trace...)
if resolved.IsResolved() {
@@ -426,7 +473,13 @@ func (p *fileLoader) resolveTypeReferenceDirectives(t *parseTask) {
increaseDepth: resolved.IsExternalLibraryImport,
elideOnDepth: false,
isFromExternalLibrary: resolved.IsExternalLibraryImport,
+ includeReason: includeReason,
}, nil)
+ } else {
+ p.includeProcessor.addProcessingDiagnostic(&processingDiagnostic{
+ kind: processingDiagnosticKindUnknownReference,
+ data: includeReason,
+ })
}
}
@@ -520,6 +573,14 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) {
increaseDepth: resolvedModule.IsExternalLibraryImport,
elideOnDepth: isJsFileFromNodeModules,
isFromExternalLibrary: resolvedModule.IsExternalLibraryImport,
+ includeReason: &fileIncludeReason{
+ kind: fileIncludeKindImport,
+ data: &referencedFileData{
+ file: t.path,
+ index: importIndex,
+ synthetic: core.IfElse(importIndex < 0, entry, nil),
+ },
+ },
}, nil)
}
}
diff --git a/internal/compiler/filesparser.go b/internal/compiler/filesparser.go
index a0f5e20df3..e4f35280da 100644
--- a/internal/compiler/filesparser.go
+++ b/internal/compiler/filesparser.go
@@ -17,11 +17,11 @@ type parseTask struct {
path tspath.Path
file *ast.SourceFile
libFile *LibFile
- isRedirected bool
+ redirectedParseTask *parseTask
subTasks []*parseTask
loaded bool
isForAutomaticTypeDirective bool
- root bool
+ includeReason *fileIncludeReason
metadata ast.SourceFileMetaData
resolutionsInFile module.ModeAwareCache[*module.ResolvedModule]
@@ -37,6 +37,9 @@ type parseTask struct {
// Track if this file is from an external library (node_modules)
// This mirrors the TypeScript currentNodeModulesDepth > 0 check
fromExternalLibrary bool
+
+ loadedTask *parseTask
+ allIncludeReasons []*fileIncludeReason
}
func (t *parseTask) FileName() string {
@@ -47,6 +50,11 @@ func (t *parseTask) Path() tspath.Path {
return t.path
}
+func (t *parseTask) isRoot() bool {
+ // Intentionally not checking t.includeReason != nil to ensure we can catch cases for missing include reason
+ return !t.isForAutomaticTypeDirective && (t.includeReason.kind == fileIncludeKindRootFile || t.includeReason.kind == fileIncludeKindLibFile)
+}
+
func (t *parseTask) load(loader *fileLoader) {
t.loaded = true
t.path = loader.toPath(t.normalizedFilePath)
@@ -74,8 +82,8 @@ func (t *parseTask) load(loader *fileLoader) {
t.file = file
t.subTasks = make([]*parseTask, 0, len(file.ReferencedFiles)+len(file.Imports())+len(file.ModuleAugmentations))
- for _, ref := range file.ReferencedFiles {
- resolvedPath := loader.resolveTripleslashPathReference(ref.FileName, file.FileName())
+ for index, ref := range file.ReferencedFiles {
+ resolvedPath := loader.resolveTripleslashPathReference(ref.FileName, file.FileName(), index)
t.addSubTask(resolvedPath, nil)
}
@@ -83,10 +91,25 @@ func (t *parseTask) load(loader *fileLoader) {
loader.resolveTypeReferenceDirectives(t)
if compilerOptions.NoLib != core.TSTrue {
- for _, lib := range file.LibReferenceDirectives {
+ for index, lib := range file.LibReferenceDirectives {
+ includeReason := &fileIncludeReason{
+ kind: fileIncludeKindLibReferenceDirective,
+ data: &referencedFileData{
+ file: t.path,
+ index: index,
+ },
+ }
if name, ok := tsoptions.GetLibFileName(lib.FileName); ok {
libFile := loader.pathForLibFile(name)
- t.addSubTask(resolvedRef{fileName: libFile.path}, libFile)
+ t.addSubTask(resolvedRef{
+ fileName: libFile.path,
+ includeReason: includeReason,
+ }, libFile)
+ } else {
+ loader.includeProcessor.addProcessingDiagnostic(&processingDiagnostic{
+ kind: processingDiagnosticKindUnknownReference,
+ data: includeReason,
+ })
}
}
}
@@ -95,9 +118,14 @@ func (t *parseTask) load(loader *fileLoader) {
}
func (t *parseTask) redirect(loader *fileLoader, fileName string) {
- t.isRedirected = true
+ t.redirectedParseTask = &parseTask{
+ normalizedFilePath: tspath.NormalizePath(fileName),
+ libFile: t.libFile,
+ fromExternalLibrary: t.fromExternalLibrary,
+ includeReason: t.includeReason,
+ }
// increaseDepth and elideOnDepth are not copied to redirects, otherwise their depth would be double counted.
- t.subTasks = []*parseTask{{normalizedFilePath: tspath.NormalizePath(fileName), libFile: t.libFile, fromExternalLibrary: t.fromExternalLibrary}}
+ t.subTasks = []*parseTask{t.redirectedParseTask}
}
func (t *parseTask) loadAutomaticTypeDirectives(loader *fileLoader) {
@@ -114,6 +142,7 @@ type resolvedRef struct {
increaseDepth bool
elideOnDepth bool
isFromExternalLibrary bool
+ includeReason *fileIncludeReason
}
func (t *parseTask) addSubTask(ref resolvedRef, libFile *LibFile) {
@@ -124,6 +153,7 @@ func (t *parseTask) addSubTask(ref resolvedRef, libFile *LibFile) {
increaseDepth: ref.increaseDepth,
elideOnDepth: ref.elideOnDepth,
fromExternalLibrary: ref.isFromExternalLibrary,
+ includeReason: ref.includeReason,
}
t.subTasks = append(t.subTasks, subTask)
}
@@ -153,7 +183,7 @@ func (w *filesParser) start(loader *fileLoader, tasks []*parseTask, depth int, i
loadedTask, loaded := w.tasksByFileName.LoadOrStore(task.FileName(), newTask)
task = loadedTask.task
if loaded {
- tasks[i] = task
+ tasks[i].loadedTask = task
// Add in the loaded task's external-ness.
taskIsFromExternalLibrary = taskIsFromExternalLibrary || task.fromExternalLibrary
}
@@ -175,7 +205,7 @@ func (w *filesParser) start(loader *fileLoader, tasks []*parseTask, depth int, i
startSubtasks = true
}
- if !task.root && taskIsFromExternalLibrary && !loadedTask.fromExternalLibrary {
+ if !task.isRoot() && taskIsFromExternalLibrary && !loadedTask.fromExternalLibrary {
// If we're seeing this task now as an external library,
// reprocess its subtasks to ensure they are also marked as external.
loadedTask.fromExternalLibrary = true
@@ -210,6 +240,17 @@ 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 {
+ 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}
+ }
+ }
// ensure we only walk each task once
if !task.loaded || !seen.AddIfAbsent(task) {
continue
diff --git a/internal/compiler/includeprocessor.go b/internal/compiler/includeprocessor.go
new file mode 100644
index 0000000000..d865d74fbb
--- /dev/null
+++ b/internal/compiler/includeprocessor.go
@@ -0,0 +1,144 @@
+package compiler
+
+import (
+ "sync"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "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/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+type includeProcessor struct {
+ fileIncludeReasons map[tspath.Path][]*fileIncludeReason
+ processingDiagnostics []*processingDiagnostic
+
+ reasonToReferenceLocation collections.SyncMap[*fileIncludeReason, *referenceFileLocation]
+ includeReasonToRelatedInfo collections.SyncMap[*fileIncludeReason, *ast.Diagnostic]
+ redirectAndFileFormat collections.SyncMap[tspath.Path, []*ast.Diagnostic]
+ computedDiagnostics *ast.DiagnosticsCollection
+ computedDiagnosticsOnce sync.Once
+ compilerOptionsSyntax *ast.ObjectLiteralExpression
+ compilerOptionsSyntaxOnce sync.Once
+}
+
+func updateFileIncludeProcessor(p *Program) {
+ p.includeProcessor = &includeProcessor{
+ fileIncludeReasons: p.includeProcessor.fileIncludeReasons,
+ processingDiagnostics: p.includeProcessor.processingDiagnostics,
+ }
+}
+
+func (i *includeProcessor) getDiagnostics(p *Program) *ast.DiagnosticsCollection {
+ i.computedDiagnosticsOnce.Do(func() {
+ i.computedDiagnostics = &ast.DiagnosticsCollection{}
+ for _, d := range i.processingDiagnostics {
+ i.computedDiagnostics.Add(d.toDiagnostic(p))
+ }
+ for _, resolutions := range p.resolvedModules {
+ for _, resolvedModule := range resolutions {
+ for _, diag := range resolvedModule.ResolutionDiagnostics {
+ i.computedDiagnostics.Add(diag)
+ }
+ }
+ }
+ for _, typeResolutions := range p.typeResolutionsInFile {
+ for _, resolvedTypeRef := range typeResolutions {
+ for _, diag := range resolvedTypeRef.ResolutionDiagnostics {
+ i.computedDiagnostics.Add(diag)
+ }
+ }
+ }
+ })
+ return i.computedDiagnostics
+}
+
+func (i *includeProcessor) addProcessingDiagnostic(d ...*processingDiagnostic) {
+ i.processingDiagnostics = append(i.processingDiagnostics, d...)
+}
+
+func (i *includeProcessor) getReferenceLocation(r *fileIncludeReason, program *Program) *referenceFileLocation {
+ if existing, ok := i.reasonToReferenceLocation.Load(r); ok {
+ return existing
+ }
+
+ loc, _ := i.reasonToReferenceLocation.LoadOrStore(r, r.getReferencedLocation(program))
+ return loc
+}
+
+func (i *includeProcessor) getCompilerOptionsObjectLiteralSyntax(program *Program) *ast.ObjectLiteralExpression {
+ i.compilerOptionsSyntaxOnce.Do(func() {
+ configFile := program.opts.Config.ConfigFile
+ if configFile != nil {
+ if compilerOptionsProperty := tsoptions.ForEachTsConfigPropArray(configFile.SourceFile, "compilerOptions", core.Identity); compilerOptionsProperty != nil &&
+ compilerOptionsProperty.Initializer != nil &&
+ ast.IsObjectLiteralExpression(compilerOptionsProperty.Initializer) {
+ i.compilerOptionsSyntax = compilerOptionsProperty.Initializer.AsObjectLiteralExpression()
+ }
+ } else {
+ i.compilerOptionsSyntax = nil
+ }
+ })
+ return i.compilerOptionsSyntax
+}
+
+func (i *includeProcessor) getRelatedInfo(r *fileIncludeReason, program *Program) *ast.Diagnostic {
+ if existing, ok := i.includeReasonToRelatedInfo.Load(r); ok {
+ return existing
+ }
+
+ relatedInfo, _ := i.includeReasonToRelatedInfo.LoadOrStore(r, r.toRelatedInfo(program))
+ return relatedInfo
+}
+
+func (i *includeProcessor) explainRedirectAndImpliedFormat(
+ program *Program,
+ file *ast.SourceFile,
+ toFileName func(fileName string) string,
+) []*ast.Diagnostic {
+ if existing, ok := i.redirectAndFileFormat.Load(file.Path()); ok {
+ return existing
+ }
+ var result []*ast.Diagnostic
+ if source := program.GetSourceOfProjectReferenceIfOutputIncluded(file); source != file.FileName() {
+ result = append(result, ast.NewCompilerDiagnostic(
+ diagnostics.File_is_output_of_project_reference_source_0,
+ toFileName(source),
+ ))
+ }
+ // !!! redirects
+ // if (file.redirectInfo) {
+ // (result ??= []).push(chainDiagnosticMessages(
+ // /*details*/ undefined,
+ // Diagnostics.File_redirects_to_file_0,
+ // toFileName(file.redirectInfo.redirectTarget, fileNameConvertor),
+ // ));
+ // }
+ if ast.IsExternalOrCommonJSModule(file) {
+ metaData := program.GetSourceFileMetaData(file.Path())
+ switch program.GetImpliedNodeFormatForEmit(file) {
+ case core.ModuleKindESNext:
+ if metaData.PackageJsonType == "module" {
+ result = append(result, ast.NewCompilerDiagnostic(
+ diagnostics.File_is_ECMAScript_module_because_0_has_field_type_with_value_module,
+ toFileName(metaData.PackageJsonDirectory+"/package.json"),
+ ))
+ }
+ case core.ModuleKindCommonJS:
+ if metaData.PackageJsonType != "" {
+ result = append(result, ast.NewCompilerDiagnostic(diagnostics.File_is_CommonJS_module_because_0_has_field_type_whose_value_is_not_module, toFileName(metaData.PackageJsonDirectory+"/package.json")))
+ } else if metaData.PackageJsonDirectory != "" {
+ if metaData.PackageJsonType == "" {
+ result = append(result, ast.NewCompilerDiagnostic(diagnostics.File_is_CommonJS_module_because_0_does_not_have_field_type, toFileName(metaData.PackageJsonDirectory+"/package.json")))
+ }
+ } else {
+ result = append(result, ast.NewCompilerDiagnostic(diagnostics.File_is_CommonJS_module_because_package_json_was_not_found))
+ }
+ }
+ }
+
+ result, _ = i.redirectAndFileFormat.LoadOrStore(file.Path(), result)
+ return result
+}
diff --git a/internal/compiler/processingDiagnostic.go b/internal/compiler/processingDiagnostic.go
new file mode 100644
index 0000000000..4fde4a9caf
--- /dev/null
+++ b/internal/compiler/processingDiagnostic.go
@@ -0,0 +1,133 @@
+package compiler
+
+import (
+ "strings"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "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/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+type processingDiagnosticKind int
+
+const (
+ processingDiagnosticKindUnknownReference processingDiagnosticKind = iota
+ processingDiagnosticKindExplainingFileInclude
+)
+
+type processingDiagnostic struct {
+ kind processingDiagnosticKind
+ data any
+}
+
+func (d *processingDiagnostic) asFileIncludeReason() *fileIncludeReason {
+ return d.data.(*fileIncludeReason)
+}
+
+type includeExplainingDiagnostic struct {
+ file tspath.Path
+ diagnosticReason *fileIncludeReason
+ message *diagnostics.Message
+ args []any
+}
+
+func (d *processingDiagnostic) asIncludeExplainingDiagnostic() *includeExplainingDiagnostic {
+ return d.data.(*includeExplainingDiagnostic)
+}
+
+func (d *processingDiagnostic) toDiagnostic(program *Program) *ast.Diagnostic {
+ switch d.kind {
+ case processingDiagnosticKindUnknownReference:
+ ref := d.asFileIncludeReason()
+ loc := ref.getReferencedLocation(program)
+ switch ref.kind {
+ case fileIncludeKindTypeReferenceDirective:
+ return loc.diagnosticAt(diagnostics.Cannot_find_type_definition_file_for_0, loc.ref.FileName)
+ case fileIncludeKindLibReferenceDirective:
+ libName := tspath.ToFileNameLowerCase(loc.ref.FileName)
+ unqualifiedLibName := strings.TrimSuffix(strings.TrimPrefix(libName, "lib."), ".d.ts")
+ suggestion := core.GetSpellingSuggestion(unqualifiedLibName, tsoptions.Libs, core.Identity)
+ return loc.diagnosticAt(core.IfElse(
+ suggestion != "",
+ diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1,
+ diagnostics.Cannot_find_lib_definition_for_0,
+ ), libName, suggestion)
+ default:
+ panic("unknown include kind")
+ }
+ case processingDiagnosticKindExplainingFileInclude:
+ return d.createDiagnosticExplainingFile(program)
+ default:
+ panic("unknown processingDiagnosticKind")
+ }
+}
+
+func (d *processingDiagnostic) createDiagnosticExplainingFile(program *Program) *ast.Diagnostic {
+ diag := d.asIncludeExplainingDiagnostic()
+ var chain []*ast.Diagnostic
+ var relatedInfo []*ast.Diagnostic
+ var redirectInfo []*ast.Diagnostic
+ var preferredLocation *fileIncludeReason
+ var seenReasons collections.Set[*fileIncludeReason]
+ if diag.diagnosticReason.isReferencedFile() && !program.includeProcessor.getReferenceLocation(diag.diagnosticReason, program).isSynthetic {
+ preferredLocation = diag.diagnosticReason
+ }
+
+ processRelatedInfo := func(includeReason *fileIncludeReason) {
+ if preferredLocation == nil && includeReason.isReferencedFile() && !program.includeProcessor.getReferenceLocation(includeReason, program).isSynthetic {
+ preferredLocation = includeReason
+ } else {
+ info := program.includeProcessor.getRelatedInfo(includeReason, program)
+ if info != nil {
+ relatedInfo = append(relatedInfo, info)
+ }
+ }
+ }
+ processInclude := func(includeReason *fileIncludeReason) {
+ if !seenReasons.AddIfAbsent(includeReason) {
+ return
+ }
+ chain = append(chain, includeReason.toDiagnostic(program, false))
+ processRelatedInfo(includeReason)
+ }
+
+ // !!! todo sheetal caching
+
+ if diag.file != "" {
+ reasons := program.includeProcessor.fileIncludeReasons[diag.file]
+ chain = make([]*ast.Diagnostic, 0, len(reasons))
+ for _, reason := range reasons {
+ processInclude(reason)
+ }
+ redirectInfo = program.includeProcessor.explainRedirectAndImpliedFormat(program, program.GetSourceFileByPath(diag.file), func(fileName string) string { return fileName })
+ }
+ if diag.diagnosticReason != nil {
+ processInclude(diag.diagnosticReason)
+ }
+ if chain != nil && (preferredLocation == nil || seenReasons.Len() != 1) {
+ fileReason := ast.NewCompilerDiagnostic(diagnostics.The_file_is_in_the_program_because_Colon)
+ fileReason.SetMessageChain(chain)
+ chain = []*ast.Diagnostic{fileReason}
+ }
+ if redirectInfo != nil {
+ chain = append(chain, redirectInfo...)
+ }
+
+ var result *ast.Diagnostic
+ if preferredLocation != nil {
+ result = program.includeProcessor.getReferenceLocation(preferredLocation, program).diagnosticAt(diag.message, diag.args...)
+ }
+ if result == nil {
+ result = ast.NewCompilerDiagnostic(diag.message, diag.args...)
+ }
+ if chain != nil {
+ result.SetMessageChain(chain)
+ }
+ if relatedInfo != nil {
+ result.SetRelatedInfo(relatedInfo)
+ }
+ return result
+}
diff --git a/internal/compiler/program.go b/internal/compiler/program.go
index 07697478f7..e801aa0021 100644
--- a/internal/compiler/program.go
+++ b/internal/compiler/program.go
@@ -3,6 +3,7 @@ package compiler
import (
"context"
"fmt"
+ "io"
"maps"
"slices"
"strings"
@@ -101,6 +102,17 @@ func (p *Program) GetRedirectTargets(path tspath.Path) []string {
return nil // !!! TODO: project references support
}
+// gets the original file that was included in program
+// this returns original source file name when including output of project reference
+// otherwise same name
+// Equivalent to originalFileName on SourceFile in Strada
+func (p *Program) GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFileName) string {
+ if source, ok := p.outputFileToProjectReferenceSource[file.Path()]; ok {
+ return source
+ }
+ return file.FileName()
+}
+
// GetOutputAndProjectReference implements checker.Program.
func (p *Program) GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
return p.projectReferenceFileMapper.getOutputAndProjectReference(path)
@@ -215,6 +227,7 @@ func (p *Program) UpdateProgram(changedFilePath tspath.Path) (*Program, bool) {
result.files[index] = newFile
result.filesByPath = maps.Clone(result.filesByPath)
result.filesByPath[newFile.Path()] = newFile
+ updateFileIncludeProcessor(result)
return result, true
}
@@ -362,7 +375,7 @@ func (p *Program) GetSuggestionDiagnostics(ctx context.Context, sourceFile *ast.
}
func (p *Program) GetProgramDiagnostics() []*ast.Diagnostic {
- return SortAndDeduplicateDiagnostics(slices.Concat(p.programDiagnostics, p.fileLoadDiagnostics.GetDiagnostics()))
+ return SortAndDeduplicateDiagnostics(slices.Concat(p.programDiagnostics, p.includeProcessor.getDiagnostics(p).GetDiagnostics()))
}
func (p *Program) getSourceFilesToEmit(targetSourceFile *ast.SourceFile, forceDtsEmit bool) []*ast.SourceFile {
@@ -410,7 +423,7 @@ func (p *Program) verifyCompilerOptions() {
createOptionDiagnosticInObjectLiteralSyntax := func(objectLiteral *ast.ObjectLiteralExpression, onKey bool, key1 string, key2 string, message *diagnostics.Message, args ...any) *ast.Diagnostic {
diag := tsoptions.ForEachPropertyAssignment(objectLiteral, key1, func(property *ast.PropertyAssignment) *ast.Diagnostic {
- return tsoptions.CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile(), core.IfElse(onKey, property.Name(), property.Initializer), message, args...)
+ return tsoptions.CreateDiagnosticForNodeInSourceFile(sourceFile(), core.IfElse(onKey, property.Name(), property.Initializer), message, args...)
}, key2)
if diag != nil {
p.programDiagnostics = append(p.programDiagnostics, diag)
@@ -422,7 +435,7 @@ func (p *Program) verifyCompilerOptions() {
compilerOptionsProperty := getCompilerOptionsPropertySyntax()
var diag *ast.Diagnostic
if compilerOptionsProperty != nil {
- diag = tsoptions.CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile(), compilerOptionsProperty.Name(), message, args...)
+ diag = tsoptions.CreateDiagnosticForNodeInSourceFile(sourceFile(), compilerOptionsProperty.Name(), message, args...)
} else {
diag = ast.NewCompilerDiagnostic(message, args...)
}
@@ -554,13 +567,14 @@ func (p *Program) verifyCompilerOptions() {
for _, file := range p.files {
if sourceFileMayBeEmitted(file, p, false) && !rootPaths.Has(file.Path()) {
- p.programDiagnostics = append(p.programDiagnostics, ast.NewDiagnostic(
- file,
- core.TextRange{},
- diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern,
- file.FileName(),
- configFilePath(),
- ))
+ p.includeProcessor.addProcessingDiagnostic(&processingDiagnostic{
+ kind: processingDiagnosticKindExplainingFileInclude,
+ data: &includeExplainingDiagnostic{
+ file: file.Path(),
+ message: diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern,
+ args: []any{file.FileName(), configFilePath()},
+ },
+ })
}
}
}
@@ -590,7 +604,7 @@ func (p *Program) verifyCompilerOptions() {
if ast.IsArrayLiteralExpression(initializer) {
elements := initializer.AsArrayLiteralExpression().Elements
if elements != nil && len(elements.Nodes) > valueIndex {
- diag := tsoptions.CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile(), elements.Nodes[valueIndex], message, args...)
+ diag := tsoptions.CreateDiagnosticForNodeInSourceFile(sourceFile(), elements.Nodes[valueIndex], message, args...)
p.programDiagnostics = append(p.programDiagnostics, diag)
return diag
}
@@ -676,6 +690,7 @@ func (p *Program) verifyCompilerOptions() {
options.SourceRoot != "" ||
options.MapRoot != "" ||
(options.GetEmitDeclarations() && options.DeclarationDir != "") {
+ // !!! sheetal checkSourceFilesBelongToPath - for root Dir and configFile - explaining why file is in the program
dir := p.CommonSourceDirectory()
if options.OutDir != "" && dir == "" && core.Some(p.files, func(f *ast.SourceFile) bool { return tspath.GetRootLength(f.FileName()) > 1 }) {
createDiagnosticForOptionName(diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir", "")
@@ -830,19 +845,7 @@ func (p *Program) IsEmitBlocked(emitFileName string) bool {
func (p *Program) verifyProjectReferences() {
buildInfoFileName := core.IfElse(!p.Options().SuppressOutputPathCheck.IsTrue(), p.opts.Config.GetBuildInfoFileName(), "")
createDiagnosticForReference := func(config *tsoptions.ParsedCommandLine, index int, message *diagnostics.Message, args ...any) {
- var sourceFile *ast.SourceFile
- if config.ConfigFile != nil {
- sourceFile = config.ConfigFile.SourceFile
- }
- diag := tsoptions.ForEachTsConfigPropArray(sourceFile, "references", func(property *ast.PropertyAssignment) *ast.Diagnostic {
- if ast.IsArrayLiteralExpression(property.Initializer) {
- value := property.Initializer.AsArrayLiteralExpression().Elements.Nodes
- if len(value) > index {
- return tsoptions.CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, value[index], message, args...)
- }
- }
- return nil
- })
+ diag := tsoptions.CreateDiagnosticAtReferenceSyntax(config, index, message, args...)
if diag == nil {
diag = ast.NewCompilerDiagnostic(message, args...)
}
@@ -1472,6 +1475,21 @@ func (p *Program) GetSourceFiles() []*ast.SourceFile {
return p.files
}
+func (p *Program) ExplainFiles(w io.Writer) {
+ toRelativeFileName := func(fileName string) string {
+ return tspath.GetRelativePathFromDirectory(p.GetCurrentDirectory(), fileName, p.comparePathsOptions)
+ }
+ for _, file := range p.GetSourceFiles() {
+ fmt.Fprintln(w, toRelativeFileName(file.FileName()))
+ for _, reason := range p.includeProcessor.fileIncludeReasons[file.Path()] {
+ fmt.Fprintln(w, " ", reason.toDiagnostic(p, true).Message())
+ }
+ for _, diag := range p.includeProcessor.explainRedirectAndImpliedFormat(p, file, toRelativeFileName) {
+ fmt.Fprintln(w, " ", diag.Message())
+ }
+ }
+}
+
func (p *Program) GetLibFileFromReference(ref *ast.FileReference) *ast.SourceFile {
path, ok := tsoptions.GetLibFileName(ref.FileName)
if !ok {
@@ -1507,25 +1525,6 @@ func (p *Program) IsSourceFileFromExternalLibrary(file *ast.SourceFile) bool {
return p.sourceFilesFoundSearchingNodeModules.Has(file.Path())
}
-type FileIncludeKind int
-
-const (
- FileIncludeKindRootFile FileIncludeKind = iota
- FileIncludeKindSourceFromProjectReference
- FileIncludeKindOutputFromProjectReference
- FileIncludeKindImport
- FileIncludeKindReferenceFile
- FileIncludeKindTypeReferenceDirective
- FileIncludeKindLibFile
- FileIncludeKindLibReferenceDirective
- FileIncludeKindAutomaticTypeDirectiveFile
-)
-
-type FileIncludeReason struct {
- Kind FileIncludeKind
- Index int
-}
-
// UnsupportedExtensions returns a list of all present "unsupported" extensions,
// e.g. extensions that are not yet supported by the port.
func (p *Program) UnsupportedExtensions() []string {
diff --git a/internal/execute/tsc.go b/internal/execute/tsc.go
index d84c373f1c..cb633671f2 100644
--- a/internal/execute/tsc.go
+++ b/internal/execute/tsc.go
@@ -311,7 +311,7 @@ func emitAndReportStatistics(
buildInfoReadTime time.Duration,
changesComputeTime time.Duration,
) ExitStatus {
- result := emitFilesAndReportErrors(sys, programLike, reportDiagnostic)
+ result := emitFilesAndReportErrors(sys, programLike, program, reportDiagnostic)
if result.status != ExitStatusSuccess {
// compile exited early
return result.status
@@ -357,14 +357,15 @@ type compileAndEmitResult struct {
func emitFilesAndReportErrors(
sys System,
- program compiler.ProgramLike,
+ programLike compiler.ProgramLike,
+ program *compiler.Program,
reportDiagnostic diagnosticReporter,
) (result compileAndEmitResult) {
ctx := context.Background()
allDiagnostics := compiler.GetDiagnosticsOfAnyProgram(
ctx,
- program,
+ programLike,
nil,
false,
func(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic {
@@ -372,22 +373,22 @@ func emitFilesAndReportErrors(
// and global diagnostics create checkers, which then bind all of the files. Do this binding
// early so we can track the time.
bindStart := sys.Now()
- diags := program.GetBindDiagnostics(ctx, file)
+ diags := programLike.GetBindDiagnostics(ctx, file)
result.bindTime = sys.Now().Sub(bindStart)
return diags
},
func(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic {
checkStart := sys.Now()
- diags := program.GetSemanticDiagnostics(ctx, file)
+ diags := programLike.GetSemanticDiagnostics(ctx, file)
result.checkTime = sys.Now().Sub(checkStart)
return diags
},
)
emitResult := &compiler.EmitResult{EmitSkipped: true, Diagnostics: []*ast.Diagnostic{}}
- if !program.Options().ListFilesOnly.IsTrue() {
+ if !programLike.Options().ListFilesOnly.IsTrue() {
emitStart := sys.Now()
- emitResult = program.Emit(ctx, compiler.EmitOptions{})
+ emitResult = programLike.Emit(ctx, compiler.EmitOptions{})
result.emitTime = sys.Now().Sub(emitStart)
}
if emitResult != nil {
@@ -406,7 +407,7 @@ func emitFilesAndReportErrors(
listFiles(sys, program)
}
- createReportErrorSummary(sys, program.Options())(allDiagnostics)
+ createReportErrorSummary(sys, programLike.Options())(allDiagnostics)
result.diagnostics = allDiagnostics
result.emitResult = emitResult
result.status = ExitStatusSuccess
@@ -422,10 +423,11 @@ func showConfig(sys System, config *core.CompilerOptions) {
_ = jsonutil.MarshalIndentWrite(sys.Writer(), config, "", " ")
}
-func listFiles(sys System, program compiler.ProgramLike) {
+func listFiles(sys System, program *compiler.Program) {
options := program.Options()
- // !!! explainFiles
- if options.ListFiles.IsTrue() || options.ListFilesOnly.IsTrue() {
+ if options.ExplainFiles.IsTrue() {
+ program.ExplainFiles(sys.Writer())
+ } else if options.ListFiles.IsTrue() || options.ListFilesOnly.IsTrue() {
for _, file := range program.GetSourceFiles() {
fmt.Fprintln(sys.Writer(), file.FileName())
}
diff --git a/internal/execute/watcher.go b/internal/execute/watcher.go
index 9b7a4ecaf7..fddd321389 100644
--- a/internal/execute/watcher.go
+++ b/internal/execute/watcher.go
@@ -88,7 +88,7 @@ func (w *Watcher) DoCycle() {
func (w *Watcher) compileAndEmit() {
// !!! output/error reporting is currently the same as non-watch mode
// diagnostics, emitResult, exitStatus :=
- emitFilesAndReportErrors(w.sys, w.program, w.reportDiagnostic)
+ emitFilesAndReportErrors(w.sys, w.program, w.program.GetProgram(), w.reportDiagnostic)
}
func (w *Watcher) hasErrorsInTsConfig() bool {
diff --git a/internal/modulespecifiers/specifiers.go b/internal/modulespecifiers/specifiers.go
index cb377869f1..fb990f12e5 100644
--- a/internal/modulespecifiers/specifiers.go
+++ b/internal/modulespecifiers/specifiers.go
@@ -34,8 +34,8 @@ func GetModuleSpecifiers(
return nil
}
modulePaths := getAllModulePathsWorker(
- getInfo(importingSourceFile.FileName(), host),
- moduleSourceFile.OriginalFileName(),
+ getInfo(host.GetSourceOfProjectReferenceIfOutputIncluded(importingSourceFile), host),
+ moduleSourceFile.FileName(),
host,
// compilerOptions,
// options,
diff --git a/internal/modulespecifiers/types.go b/internal/modulespecifiers/types.go
index c6727aa022..309fc8ab6c 100644
--- a/internal/modulespecifiers/types.go
+++ b/internal/modulespecifiers/types.go
@@ -12,7 +12,6 @@ import (
type SourceFileForSpecifierGeneration interface {
Path() tspath.Path
FileName() string
- OriginalFileName() string
Imports() []*ast.StringLiteralLike
IsJS() bool
}
@@ -55,6 +54,7 @@ type ModuleSpecifierGenerationHost interface {
GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference
GetRedirectTargets(path tspath.Path) []string
+ GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFileName) string
FileExists(path string) bool
diff --git a/internal/project/configfileregistry.go b/internal/project/configfileregistry.go
index 26b9060ba9..fc4600e4af 100644
--- a/internal/project/configfileregistry.go
+++ b/internal/project/configfileregistry.go
@@ -101,7 +101,7 @@ func (c *ConfigFileRegistry) acquireConfig(fileName string, path tspath.Path, pr
}
switch entry.pendingReload {
case PendingReloadFileNames:
- entry.commandLine = tsoptions.ReloadFileNamesOfParsedCommandLine(entry.commandLine, c.Host.FS())
+ entry.commandLine = entry.commandLine.ReloadFileNamesOfParsedCommandLine(c.Host.FS())
case PendingReloadFull:
oldCommandLine := entry.commandLine
entry.commandLine, _ = tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, nil, c.Host, &c.ExtendedConfigCache)
diff --git a/internal/transformers/jsxtransforms/jsx.go b/internal/transformers/jsxtransforms/jsx.go
index 54a2dcecf3..306f181f00 100644
--- a/internal/transformers/jsxtransforms/jsx.go
+++ b/internal/transformers/jsxtransforms/jsx.go
@@ -47,7 +47,7 @@ func (tx *JSXTransformer) getCurrentFileNameExpression() *ast.Node {
}),
nil,
nil,
- tx.Factory().NewStringLiteral(tx.currentSourceFile.OriginalFileName()),
+ tx.Factory().NewStringLiteral(tx.currentSourceFile.FileName()),
)
tx.filenameDeclaration = d
return d.AsVariableDeclaration().Name()
diff --git a/internal/transformers/tstransforms/importelision_test.go b/internal/transformers/tstransforms/importelision_test.go
index f7d8b9c043..aae14ac707 100644
--- a/internal/transformers/tstransforms/importelision_test.go
+++ b/internal/transformers/tstransforms/importelision_test.go
@@ -76,6 +76,10 @@ func (p *fakeProgram) GetRedirectTargets(path tspath.Path) []string {
return nil
}
+func (p *fakeProgram) GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFileName) string {
+ return ""
+}
+
func (p *fakeProgram) GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
return nil
}
diff --git a/internal/tsoptions/errors.go b/internal/tsoptions/errors.go
index 305693a9dd..ef56e1ddb3 100644
--- a/internal/tsoptions/errors.go
+++ b/internal/tsoptions/errors.go
@@ -78,9 +78,13 @@ func createUnknownOptionError(
return CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, unknownOptionDiagnostic, unknownOptionErrorText)
}
+func CreateDiagnosticForNodeInSourceFile(sourceFile *ast.SourceFile, node *ast.Node, message *diagnostics.Message, args ...any) *ast.Diagnostic {
+ return ast.NewDiagnostic(sourceFile, core.NewTextRange(scanner.SkipTrivia(sourceFile.Text(), node.Loc.Pos()), node.End()), message, args...)
+}
+
func CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile *ast.SourceFile, node *ast.Node, message *diagnostics.Message, args ...any) *ast.Diagnostic {
if sourceFile != nil && node != nil {
- return ast.NewDiagnostic(sourceFile, core.NewTextRange(scanner.SkipTrivia(sourceFile.Text(), node.Loc.Pos()), node.End()), message, args...)
+ return CreateDiagnosticForNodeInSourceFile(sourceFile, node, message, args...)
}
return ast.NewCompilerDiagnostic(message, args...)
}
diff --git a/internal/tsoptions/parsedcommandline.go b/internal/tsoptions/parsedcommandline.go
index 8d36f04811..a265f7dc87 100644
--- a/internal/tsoptions/parsedcommandline.go
+++ b/internal/tsoptions/parsedcommandline.go
@@ -270,10 +270,26 @@ func (p *ParsedCommandLine) MatchesFileName(fileName string) bool {
return false
}
- return p.ConfigFile.configFileSpecs.matchesInclude(fileName, p.comparePathsOptions)
+ return p.ConfigFile.configFileSpecs.getMatchedIncludeSpec(fileName, p.comparePathsOptions) != ""
}
-func ReloadFileNamesOfParsedCommandLine(p *ParsedCommandLine, fs vfs.FS) *ParsedCommandLine {
+func (p *ParsedCommandLine) GetMatchedFileSpec(fileName string) string {
+ return p.ConfigFile.configFileSpecs.getMatchedFileSpec(fileName, p.comparePathsOptions)
+}
+
+func (p *ParsedCommandLine) GetMatchedIncludeSpec(fileName string) (string, bool) {
+ if len(p.ConfigFile.configFileSpecs.validatedIncludeSpecs) == 0 {
+ return "", false
+ }
+
+ if p.ConfigFile.configFileSpecs.isDefaultIncludeSpec {
+ return p.ConfigFile.configFileSpecs.validatedIncludeSpecs[0], true
+ }
+
+ return p.ConfigFile.configFileSpecs.getMatchedIncludeSpec(fileName, p.comparePathsOptions), false
+}
+
+func (p *ParsedCommandLine) ReloadFileNamesOfParsedCommandLine(fs vfs.FS) *ParsedCommandLine {
parsedConfig := *p.ParsedConfig
parsedConfig.FileNames = getFileNamesFromConfigSpecs(
*p.ConfigFile.configFileSpecs,
diff --git a/internal/tsoptions/parsedcommandline_test.go b/internal/tsoptions/parsedcommandline_test.go
index 81d324331a..0185e6abe0 100644
--- a/internal/tsoptions/parsedcommandline_test.go
+++ b/internal/tsoptions/parsedcommandline_test.go
@@ -105,7 +105,7 @@ func TestParsedCommandLine(t *testing.T) {
"/dev/b.ts",
})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/a.ts",
"/dev/b.ts",
@@ -135,7 +135,7 @@ func TestParsedCommandLine(t *testing.T) {
"/dev/b.ts",
})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/a.ts",
"/dev/b.ts",
@@ -159,7 +159,7 @@ func TestParsedCommandLine(t *testing.T) {
assertMatches(t, parsedCommandLine, files, []string{})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{})
})
@@ -185,7 +185,7 @@ func TestParsedCommandLine(t *testing.T) {
"/dev/a.ts",
})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/a.ts",
})
@@ -220,7 +220,7 @@ func TestParsedCommandLine(t *testing.T) {
"/dev/z/aba.ts",
})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/z/a.ts",
"/dev/z/aba.ts",
@@ -251,7 +251,7 @@ func TestParsedCommandLine(t *testing.T) {
})
// a.d.ts matches if a.ts is not already included
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/a.ts",
"/dev/a.d.ts",
@@ -279,7 +279,7 @@ func TestParsedCommandLine(t *testing.T) {
"/dev/x/b.ts",
})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/x/a.ts",
"/dev/x/b.ts",
@@ -302,7 +302,7 @@ func TestParsedCommandLine(t *testing.T) {
assertMatches(t, parsedCommandLine, files, []string{})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{})
})
@@ -328,7 +328,7 @@ func TestParsedCommandLine(t *testing.T) {
"/dev/js/b.js",
})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/js/a.js",
"/dev/js/b.js",
@@ -357,7 +357,7 @@ func TestParsedCommandLine(t *testing.T) {
"/dev/js/ab.min.js",
})
- emptyParsedCommandLine := tsoptions.ReloadFileNamesOfParsedCommandLine(parsedCommandLine, noFilesFS)
+ emptyParsedCommandLine := parsedCommandLine.ReloadFileNamesOfParsedCommandLine(noFilesFS)
assertMatches(t, emptyParsedCommandLine, noFiles, []string{
"/dev/js/d.min.js",
"/dev/js/ab.min.js",
diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go
index 8a90a3475b..ca6757f048 100644
--- a/internal/tsoptions/tsconfigparsing.go
+++ b/internal/tsoptions/tsconfigparsing.go
@@ -15,7 +15,6 @@ import (
"github.com/microsoft/typescript-go/internal/jsnum"
"github.com/microsoft/typescript-go/internal/module"
"github.com/microsoft/typescript-go/internal/parser"
- "github.com/microsoft/typescript-go/internal/scanner"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
)
@@ -91,11 +90,13 @@ type configFileSpecs struct {
// Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching
includeSpecs any
// Present to report errors (user specified specs), validatedExcludeSpecs are used for file name matching
- excludeSpecs any
- validatedFilesSpec []string
- validatedIncludeSpecs []string
- validatedExcludeSpecs []string
- isDefaultIncludeSpec bool
+ excludeSpecs any
+ validatedFilesSpec []string
+ validatedIncludeSpecs []string
+ validatedExcludeSpecs []string
+ validatedFilesSpecBeforeSubstitution []string
+ validatedIncludeSpecsBeforeSubstitution []string
+ isDefaultIncludeSpec bool
}
func (c *configFileSpecs) matchesExclude(fileName string, comparePathsOptions tspath.ComparePathsOptions) bool {
@@ -115,20 +116,33 @@ func (c *configFileSpecs) matchesExclude(fileName string, comparePathsOptions ts
return false
}
-func (c *configFileSpecs) matchesInclude(fileName string, comparePathsOptions tspath.ComparePathsOptions) bool {
+func (c *configFileSpecs) getMatchedIncludeSpec(fileName string, comparePathsOptions tspath.ComparePathsOptions) string {
if len(c.validatedIncludeSpecs) == 0 {
- return false
+ return ""
}
- for _, spec := range c.validatedIncludeSpecs {
+ for index, spec := range c.validatedIncludeSpecs {
includePattern := vfs.GetPatternFromSpec(spec, comparePathsOptions.CurrentDirectory, "files")
if includePattern != "" {
includeRegex := vfs.GetRegexFromPattern(includePattern, comparePathsOptions.UseCaseSensitiveFileNames)
if match, err := includeRegex.MatchString(fileName); err == nil && match {
- return true
+ return c.validatedIncludeSpecsBeforeSubstitution[index]
}
}
}
- return false
+ return ""
+}
+
+func (c *configFileSpecs) getMatchedFileSpec(fileName string, comparePathsOptions tspath.ComparePathsOptions) string {
+ if len(c.validatedFilesSpec) == 0 {
+ return ""
+ }
+ filePath := tspath.ToPath(fileName, comparePathsOptions.CurrentDirectory, comparePathsOptions.UseCaseSensitiveFileNames)
+ for index, spec := range c.validatedFilesSpec {
+ if tspath.ToPath(spec, comparePathsOptions.CurrentDirectory, comparePathsOptions.UseCaseSensitiveFileNames) == filePath {
+ return c.validatedFilesSpecBeforeSubstitution[index]
+ }
+ }
+ return ""
}
type FileExtensionInfo struct {
@@ -208,7 +222,7 @@ func parseOwnConfigOfJsonSourceFile(
propertySetErrors = append(propertySetErrors, err...)
} else if option == nil {
if keyText == "excludes" {
- propertySetErrors = append(propertySetErrors, CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, propertyAssignment.Name(), diagnostics.Unknown_option_excludes_Did_you_mean_exclude))
+ propertySetErrors = append(propertySetErrors, CreateDiagnosticForNodeInSourceFile(sourceFile, propertyAssignment.Name(), diagnostics.Unknown_option_excludes_Did_you_mean_exclude))
}
if core.Find(OptionsDeclarations, func(option *CommandLineOption) bool { return option.Name == keyText }) != nil {
rootCompilerOptions = append(rootCompilerOptions, propertyAssignment.Name())
@@ -1171,7 +1185,7 @@ func parseJsonConfigFileContentWorker(
}
diagnosticMessage := diagnostics.The_files_list_in_config_file_0_is_empty
nodeValue := ForEachTsConfigPropArray(sourceFile.SourceFile, "files", func(property *ast.PropertyAssignment) *ast.Node { return property.Initializer })
- errors = append(errors, ast.NewDiagnostic(sourceFile.SourceFile, core.NewTextRange(scanner.SkipTrivia(sourceFile.SourceFile.Text(), nodeValue.Pos()), nodeValue.End()), diagnosticMessage, fileName))
+ errors = append(errors, CreateDiagnosticForNodeInSourceFile(sourceFile.SourceFile, nodeValue, diagnosticMessage, fileName))
} else {
errors = append(errors, ast.NewCompilerDiagnostic(diagnostics.The_files_list_in_config_file_0_is_empty, configFileName))
}
@@ -1199,31 +1213,39 @@ func parseJsonConfigFileContentWorker(
isDefaultIncludeSpec = true
}
var validatedIncludeSpecs []string
+ var validatedIncludeSpecsBeforeSubstitution []string
var validatedExcludeSpecs []string
var validatedFilesSpec []string
+ var validatedFilesSpecBeforeSubstitution []string
// The exclude spec list is converted into a regular expression, which allows us to quickly
// test whether a file or directory should be excluded before recursively traversing the
// file system.
if includeSpecs.sliceValue != nil {
var err []*ast.Diagnostic
- validatedIncludeSpecs, err = validateSpecs(includeSpecs.sliceValue, true /*disallowTrailingRecursion*/, tsconfigToSourceFile(sourceFile), "include")
+ validatedIncludeSpecsBeforeSubstitution, err = validateSpecs(includeSpecs.sliceValue, true /*disallowTrailingRecursion*/, tsconfigToSourceFile(sourceFile), "include")
errors = append(errors, err...)
- substituteStringArrayWithConfigDirTemplate(validatedIncludeSpecs, basePathForFileNames)
+ if validatedIncludeSpecs = getSubstitutedStringArrayWithConfigDirTemplate(validatedIncludeSpecsBeforeSubstitution, basePathForFileNames); validatedIncludeSpecs == nil {
+ validatedIncludeSpecs = validatedIncludeSpecsBeforeSubstitution
+ }
}
if excludeSpecs.sliceValue != nil {
var err []*ast.Diagnostic
validatedExcludeSpecs, err = validateSpecs(excludeSpecs.sliceValue, false /*disallowTrailingRecursion*/, tsconfigToSourceFile(sourceFile), "exclude")
errors = append(errors, err...)
- substituteStringArrayWithConfigDirTemplate(validatedExcludeSpecs, basePathForFileNames)
+ if validatedExcludeSpecsWithSubstitution := getSubstitutedStringArrayWithConfigDirTemplate(validatedExcludeSpecs, basePathForFileNames); validatedExcludeSpecsWithSubstitution != nil {
+ validatedExcludeSpecs = validatedExcludeSpecsWithSubstitution
+ }
}
if fileSpecs.sliceValue != nil {
fileSpecs := core.Filter(fileSpecs.sliceValue, func(spec any) bool { return reflect.TypeOf(spec).Kind() == reflect.String })
for _, spec := range fileSpecs {
if spec, ok := spec.(string); ok {
- validatedFilesSpec = append(validatedFilesSpec, spec)
+ validatedFilesSpecBeforeSubstitution = append(validatedFilesSpecBeforeSubstitution, spec)
}
}
- substituteStringArrayWithConfigDirTemplate(validatedFilesSpec, basePathForFileNames)
+ if validatedFilesSpec = getSubstitutedStringArrayWithConfigDirTemplate(validatedFilesSpecBeforeSubstitution, basePathForFileNames); validatedFilesSpec == nil {
+ validatedFilesSpec = validatedFilesSpecBeforeSubstitution
+ }
}
configFileSpecs := configFileSpecs{
fileSpecs.sliceValue,
@@ -1232,6 +1254,8 @@ func parseJsonConfigFileContentWorker(
validatedFilesSpec,
validatedIncludeSpecs,
validatedExcludeSpecs,
+ validatedFilesSpecBeforeSubstitution,
+ validatedIncludeSpecsBeforeSubstitution,
isDefaultIncludeSpec,
}
@@ -1311,7 +1335,7 @@ func shouldReportNoInputFiles(fileNames []string, canJsonReportNoInputFiles bool
func validateSpecs(specs any, disallowTrailingRecursion bool, jsonSourceFile *ast.SourceFile, specKey string) ([]string, []*ast.Diagnostic) {
createDiagnostic := func(message *diagnostics.Message, spec string) *ast.Diagnostic {
- element := getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec)
+ element := GetTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec)
return CreateDiagnosticForNodeInSourceFileOrCompilerDiagnostic(jsonSourceFile, element.AsNode(), message, spec)
}
var errors []*ast.Diagnostic
@@ -1377,15 +1401,11 @@ func invalidDotDotAfterRecursiveWildcard(s string) bool {
// \/?$ # matches an optional trailing directory separator at the end of the string.
const invalidTrailingRecursionPattern = `(?:^|\/)\*\*\/?$`
-func getTsConfigPropArrayElementValue(tsConfigSourceFile *ast.SourceFile, propKey string, elementValue string) *ast.StringLiteral {
+func GetTsConfigPropArrayElementValue(tsConfigSourceFile *ast.SourceFile, propKey string, elementValue string) *ast.StringLiteral {
+ callback := GetCallbackForFindingPropertyAssignmentByValue(elementValue)
return ForEachTsConfigPropArray(tsConfigSourceFile, propKey, func(property *ast.PropertyAssignment) *ast.StringLiteral {
- if ast.IsArrayLiteralExpression(property.Initializer) {
- value := core.Find(property.Initializer.AsArrayLiteralExpression().Elements.Nodes, func(element *ast.Node) bool {
- return ast.IsStringLiteral(element) && element.AsStringLiteral().Text == elementValue
- })
- if value != nil {
- return value.AsStringLiteral()
- }
+ if value := callback(property); value != nil {
+ return value.AsStringLiteral()
}
return nil
})
@@ -1398,6 +1418,33 @@ func ForEachTsConfigPropArray[T any](tsConfigSourceFile *ast.SourceFile, propKey
return nil
}
+func CreateDiagnosticAtReferenceSyntax(config *ParsedCommandLine, index int, message *diagnostics.Message, args ...any) *ast.Diagnostic {
+ return ForEachTsConfigPropArray(config.ConfigFile.SourceFile, "references", func(property *ast.PropertyAssignment) *ast.Diagnostic {
+ if ast.IsArrayLiteralExpression(property.Initializer) {
+ value := property.Initializer.AsArrayLiteralExpression().Elements.Nodes
+ if len(value) > index {
+ return CreateDiagnosticForNodeInSourceFile(config.ConfigFile.SourceFile, value[index], message, args...)
+ }
+ }
+ return nil
+ })
+}
+
+func GetCallbackForFindingPropertyAssignmentByValue(value string) func(property *ast.PropertyAssignment) *ast.Node {
+ return func(property *ast.PropertyAssignment) *ast.Node {
+ if ast.IsArrayLiteralExpression(property.Initializer) {
+ return core.Find(property.Initializer.AsArrayLiteralExpression().Elements.Nodes, func(element *ast.Node) bool {
+ return ast.IsStringLiteral(element) && element.AsStringLiteral().Text == value
+ })
+ }
+ return nil
+ }
+}
+
+func GetOptionsSyntaxByArrayElementValue(objectLiteral *ast.ObjectLiteralExpression, propKey string, elementValue string) *ast.Node {
+ return ForEachPropertyAssignment(objectLiteral, propKey, GetCallbackForFindingPropertyAssignmentByValue(elementValue))
+}
+
func ForEachPropertyAssignment[T any](objectLiteral *ast.ObjectLiteralExpression, key string, callback func(property *ast.PropertyAssignment) *T, key2 ...string) *T {
if objectLiteral != nil {
for _, property := range objectLiteral.Properties.Nodes {
@@ -1426,12 +1473,20 @@ func getSubstitutedPathWithConfigDirTemplate(value string, basePath string) stri
return tspath.GetNormalizedAbsolutePath(strings.Replace(value, configDirTemplate, "./", 1), basePath)
}
-func substituteStringArrayWithConfigDirTemplate(list []string, basePath string) {
+func getSubstitutedStringArrayWithConfigDirTemplate(list []string, basePath string) []string {
+ var result []string
for i, element := range list {
if startsWithConfigDirTemplate(element) {
- list[i] = getSubstitutedPathWithConfigDirTemplate(element, basePath)
+ if result == nil {
+ result = slices.Clone(list)
+ }
+ result[i] = getSubstitutedPathWithConfigDirTemplate(element, basePath)
}
}
+ if result != nil {
+ return result
+ }
+ return nil
}
func handleOptionConfigDirTemplateSubstitution(compilerOptions *core.CompilerOptions, basePath string) {
@@ -1441,13 +1496,18 @@ func handleOptionConfigDirTemplateSubstitution(compilerOptions *core.CompilerOpt
// !!! don't hardcode this; use options declarations?
- for v := range compilerOptions.Paths.Values() {
- substituteStringArrayWithConfigDirTemplate(v, basePath)
+ for k, v := range compilerOptions.Paths.Entries() {
+ if substitution := getSubstitutedStringArrayWithConfigDirTemplate(v, basePath); substitution != nil {
+ compilerOptions.Paths.Set(k, substitution)
+ }
}
- substituteStringArrayWithConfigDirTemplate(compilerOptions.RootDirs, basePath)
- substituteStringArrayWithConfigDirTemplate(compilerOptions.TypeRoots, basePath)
-
+ if rootDirs := getSubstitutedStringArrayWithConfigDirTemplate(compilerOptions.RootDirs, basePath); rootDirs != nil {
+ compilerOptions.RootDirs = rootDirs
+ }
+ if typeRoots := getSubstitutedStringArrayWithConfigDirTemplate(compilerOptions.TypeRoots, basePath); typeRoots != nil {
+ compilerOptions.TypeRoots = typeRoots
+ }
if startsWithConfigDirTemplate(compilerOptions.GenerateCpuProfile) {
compilerOptions.GenerateCpuProfile = getSubstitutedPathWithConfigDirTemplate(compilerOptions.GenerateCpuProfile, basePath)
}
diff --git a/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt b/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt
index bde23ab460..15ac745a8f 100644
--- a/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt
+++ b/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt
@@ -1,10 +1,13 @@
+/app/app.ts(2,23): error TS2688: Cannot find type definition file for 'linked'.
/app/app.ts(4,25): error TS2307: Cannot find module 'linked' or its corresponding type declarations.
/app/app.ts(5,25): error TS2307: Cannot find module 'linked2' or its corresponding type declarations.
-==== /app/app.ts (2 errors) ====
+==== /app/app.ts (3 errors) ====
// We shouldn't resolve symlinks for references either. See the trace.
///
+ ~~~~~~
+!!! error TS2688: Cannot find type definition file for 'linked'.
import { C as C1 } from "linked";
~~~~~~~~
diff --git a/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt.diff b/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt.diff
index ddd0f79e76..4a31f74d95 100644
--- a/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt.diff
+++ b/testdata/baselines/reference/submodule/compiler/moduleResolutionWithSymlinks_preserveSymlinks.errors.txt.diff
@@ -6,13 +6,16 @@
-
-
-==== /app/app.ts (1 errors) ====
++/app/app.ts(2,23): error TS2688: Cannot find type definition file for 'linked'.
+/app/app.ts(4,25): error TS2307: Cannot find module 'linked' or its corresponding type declarations.
+/app/app.ts(5,25): error TS2307: Cannot find module 'linked2' or its corresponding type declarations.
+
+
-+==== /app/app.ts (2 errors) ====
++==== /app/app.ts (3 errors) ====
// We shouldn't resolve symlinks for references either. See the trace.
///
++ ~~~~~~
++!!! error TS2688: Cannot find type definition file for 'linked'.
import { C as C1 } from "linked";
+ ~~~~~~~~
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt
new file mode 100644
index 0000000000..9062d29947
--- /dev/null
+++ b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt
@@ -0,0 +1,17 @@
+usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
+
+
+==== node_modules/pkg/index.d.ts (0 errors) ====
+ interface GlobalThing { a: number }
+==== node_modules/pkg/package.json (0 errors) ====
+ {
+ "name": "pkg",
+ "types": "index.d.ts",
+ "exports": "some-other-thing.js"
+ }
+==== usage.ts (1 errors) ====
+ ///
+ ~~~
+!!! error TS2688: Cannot find type definition file for 'pkg'.
+
+ const a: GlobalThing = { a: 0 };
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt.diff b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt.diff
new file mode 100644
index 0000000000..d1bf09c663
--- /dev/null
+++ b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt.diff
@@ -0,0 +1,21 @@
+--- old.tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt
++++ new.tripleSlashTypesReferenceWithMissingExports(module=commonjs).errors.txt
+@@= skipped -0, +0 lines =@@
+-
++usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
++
++
++==== node_modules/pkg/index.d.ts (0 errors) ====
++ interface GlobalThing { a: number }
++==== node_modules/pkg/package.json (0 errors) ====
++ {
++ "name": "pkg",
++ "types": "index.d.ts",
++ "exports": "some-other-thing.js"
++ }
++==== usage.ts (1 errors) ====
++ ///
++ ~~~
++!!! error TS2688: Cannot find type definition file for 'pkg'.
++
++ const a: GlobalThing = { a: 0 };
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt
new file mode 100644
index 0000000000..9062d29947
--- /dev/null
+++ b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt
@@ -0,0 +1,17 @@
+usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
+
+
+==== node_modules/pkg/index.d.ts (0 errors) ====
+ interface GlobalThing { a: number }
+==== node_modules/pkg/package.json (0 errors) ====
+ {
+ "name": "pkg",
+ "types": "index.d.ts",
+ "exports": "some-other-thing.js"
+ }
+==== usage.ts (1 errors) ====
+ ///
+ ~~~
+!!! error TS2688: Cannot find type definition file for 'pkg'.
+
+ const a: GlobalThing = { a: 0 };
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt.diff b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt.diff
deleted file mode 100644
index f38980ad8b..0000000000
--- a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt.diff
+++ /dev/null
@@ -1,21 +0,0 @@
---- old.tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt
-+++ new.tripleSlashTypesReferenceWithMissingExports(module=node16).errors.txt
-@@= skipped -0, +0 lines =@@
--usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
--
--
--==== node_modules/pkg/index.d.ts (0 errors) ====
-- interface GlobalThing { a: number }
--==== node_modules/pkg/package.json (0 errors) ====
-- {
-- "name": "pkg",
-- "types": "index.d.ts",
-- "exports": "some-other-thing.js"
-- }
--==== usage.ts (1 errors) ====
-- ///
-- ~~~
--!!! error TS2688: Cannot find type definition file for 'pkg'.
--
-- const a: GlobalThing = { a: 0 };
-+
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt
new file mode 100644
index 0000000000..9062d29947
--- /dev/null
+++ b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt
@@ -0,0 +1,17 @@
+usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
+
+
+==== node_modules/pkg/index.d.ts (0 errors) ====
+ interface GlobalThing { a: number }
+==== node_modules/pkg/package.json (0 errors) ====
+ {
+ "name": "pkg",
+ "types": "index.d.ts",
+ "exports": "some-other-thing.js"
+ }
+==== usage.ts (1 errors) ====
+ ///
+ ~~~
+!!! error TS2688: Cannot find type definition file for 'pkg'.
+
+ const a: GlobalThing = { a: 0 };
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt.diff b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt.diff
deleted file mode 100644
index 8cbb190eb4..0000000000
--- a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt.diff
+++ /dev/null
@@ -1,21 +0,0 @@
---- old.tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt
-+++ new.tripleSlashTypesReferenceWithMissingExports(module=node18).errors.txt
-@@= skipped -0, +0 lines =@@
--usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
--
--
--==== node_modules/pkg/index.d.ts (0 errors) ====
-- interface GlobalThing { a: number }
--==== node_modules/pkg/package.json (0 errors) ====
-- {
-- "name": "pkg",
-- "types": "index.d.ts",
-- "exports": "some-other-thing.js"
-- }
--==== usage.ts (1 errors) ====
-- ///
-- ~~~
--!!! error TS2688: Cannot find type definition file for 'pkg'.
--
-- const a: GlobalThing = { a: 0 };
-+
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt
new file mode 100644
index 0000000000..9062d29947
--- /dev/null
+++ b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt
@@ -0,0 +1,17 @@
+usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
+
+
+==== node_modules/pkg/index.d.ts (0 errors) ====
+ interface GlobalThing { a: number }
+==== node_modules/pkg/package.json (0 errors) ====
+ {
+ "name": "pkg",
+ "types": "index.d.ts",
+ "exports": "some-other-thing.js"
+ }
+==== usage.ts (1 errors) ====
+ ///
+ ~~~
+!!! error TS2688: Cannot find type definition file for 'pkg'.
+
+ const a: GlobalThing = { a: 0 };
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt.diff b/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt.diff
deleted file mode 100644
index 02e1361b29..0000000000
--- a/testdata/baselines/reference/submodule/compiler/tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt.diff
+++ /dev/null
@@ -1,21 +0,0 @@
---- old.tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt
-+++ new.tripleSlashTypesReferenceWithMissingExports(module=nodenext).errors.txt
-@@= skipped -0, +0 lines =@@
--usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.
--
--
--==== node_modules/pkg/index.d.ts (0 errors) ====
-- interface GlobalThing { a: number }
--==== node_modules/pkg/package.json (0 errors) ====
-- {
-- "name": "pkg",
-- "types": "index.d.ts",
-- "exports": "some-other-thing.js"
-- }
--==== usage.ts (1 errors) ====
-- ///
-- ~~~
--!!! error TS2688: Cannot find type definition file for 'pkg'.
--
-- const a: GlobalThing = { a: 0 };
-+
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/conformance/typingsLookup3.errors.txt b/testdata/baselines/reference/submodule/conformance/typingsLookup3.errors.txt
new file mode 100644
index 0000000000..5073cb5493
--- /dev/null
+++ b/testdata/baselines/reference/submodule/conformance/typingsLookup3.errors.txt
@@ -0,0 +1,15 @@
+/a.ts(1,23): error TS2688: Cannot find type definition file for 'JqUeRy'.
+
+
+==== /tsconfig.json (0 errors) ====
+ { "files": "a.ts" }
+
+==== /a.ts (1 errors) ====
+ ///
+ ~~~~~~
+!!! error TS2688: Cannot find type definition file for 'JqUeRy'.
+ $.x;
+
+==== /node_modules/@types/jquery/index.d.ts (0 errors) ====
+ declare var $: { x: any };
+
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/conformance/typingsLookup3.errors.txt.diff b/testdata/baselines/reference/submodule/conformance/typingsLookup3.errors.txt.diff
deleted file mode 100644
index 8c57b37ae7..0000000000
--- a/testdata/baselines/reference/submodule/conformance/typingsLookup3.errors.txt.diff
+++ /dev/null
@@ -1,19 +0,0 @@
---- old.typingsLookup3.errors.txt
-+++ new.typingsLookup3.errors.txt
-@@= skipped -0, +0 lines =@@
--/a.ts(1,23): error TS2688: Cannot find type definition file for 'JqUeRy'.
--
--
--==== /tsconfig.json (0 errors) ====
-- { "files": "a.ts" }
--
--==== /a.ts (1 errors) ====
-- ///
-- ~~~~~~
--!!! error TS2688: Cannot find type definition file for 'JqUeRy'.
-- $.x;
--
--==== /node_modules/@types/jquery/index.d.ts (0 errors) ====
-- declare var $: { x: any };
--
-+
\ No newline at end of file
diff --git a/testdata/baselines/reference/tsc/extends/configDir-template-with-commandline.js b/testdata/baselines/reference/tsc/extends/configDir-template-with-commandline.js
index 53a217d65b..02de299024 100644
--- a/testdata/baselines/reference/tsc/extends/configDir-template-with-commandline.js
+++ b/testdata/baselines/reference/tsc/extends/configDir-template-with-commandline.js
@@ -106,6 +106,14 @@ Directory '/node_modules' does not exist, skipping all lookups in it.
[7m3[0m "compilerOptions": {
[7m [0m [91m ~~~~~~~~~~~~~~~~~[0m
+../../tslibs/TS/Lib/lib.d.ts
+ Default library for target 'ES5'
+types/sometype.ts
+ Imported via @myscope/sometype from file 'main.ts'
+main.ts
+ Part of 'files' list in tsconfig.json
+src/secondary.ts
+ Matched by include pattern '${configDir}/src' in 'tsconfig.json'
Found 2 errors in the same file, starting at: tsconfig.json[90m:3[0m
diff --git a/testdata/baselines/reference/tsc/extends/configDir-template.js b/testdata/baselines/reference/tsc/extends/configDir-template.js
index 5649382f33..6a0adf8b7d 100644
--- a/testdata/baselines/reference/tsc/extends/configDir-template.js
+++ b/testdata/baselines/reference/tsc/extends/configDir-template.js
@@ -106,6 +106,14 @@ Directory '/node_modules' does not exist, skipping all lookups in it.
[7m3[0m "compilerOptions": {
[7m [0m [91m ~~~~~~~~~~~~~~~~~[0m
+../../tslibs/TS/Lib/lib.d.ts
+ Default library for target 'ES5'
+types/sometype.ts
+ Imported via @myscope/sometype from file 'main.ts'
+main.ts
+ Part of 'files' list in tsconfig.json
+src/secondary.ts
+ Matched by include pattern '${configDir}/src' in 'tsconfig.json'
Found 2 errors in the same file, starting at: tsconfig.json[90m:3[0m
diff --git a/testdata/baselines/reference/tsc/incremental/when-passing-filename-for-buildinfo-on-commandline.js b/testdata/baselines/reference/tsc/incremental/when-passing-filename-for-buildinfo-on-commandline.js
index a51814d710..99ad44a329 100644
--- a/testdata/baselines/reference/tsc/incremental/when-passing-filename-for-buildinfo-on-commandline.js
+++ b/testdata/baselines/reference/tsc/incremental/when-passing-filename-for-buildinfo-on-commandline.js
@@ -17,6 +17,10 @@ export const x = 10;
tsgo --incremental --tsBuildInfoFile .tsbuildinfo --explainFiles
ExitStatus:: Success
Output::
+../../tslibs/TS/Lib/lib.d.ts
+ Default library for target 'ES5'
+src/main.ts
+ Matched by include pattern 'src/**/*.ts' in 'tsconfig.json'
//// [/home/src/tslibs/TS/Lib/lib.d.ts] *Lib*
///
interface Boolean {}
@@ -94,6 +98,10 @@ Edit [0]:: no change
tsgo --incremental --tsBuildInfoFile .tsbuildinfo --explainFiles
ExitStatus:: Success
Output::
+../../tslibs/TS/Lib/lib.d.ts
+ Default library for target 'ES5'
+src/main.ts
+ Matched by include pattern 'src/**/*.ts' in 'tsconfig.json'
SemanticDiagnostics::
Signatures::