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. 3 "compilerOptions": {    ~~~~~~~~~~~~~~~~~ +../../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:3 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. 3 "compilerOptions": {    ~~~~~~~~~~~~~~~~~ +../../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:3 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::