Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 34 additions & 26 deletions internal/compiler/fileloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ import (
"github.com/microsoft/typescript-go/internal/tspath"
)

type LibFile struct {
Name string
path string
Replaced bool
}

type fileLoader struct {
opts ProgramOptions
resolver *module.Resolver
Expand All @@ -34,7 +40,7 @@ type fileLoader struct {
projectReferenceFileMapper *projectReferenceFileMapper
dtsDirectories collections.Set[tspath.Path]

pathForLibFileCache collections.SyncMap[string, string]
pathForLibFileCache collections.SyncMap[string, *LibFile]
pathForLibFileResolutions collections.SyncMap[tspath.Path, module.ModeAwareCache[*module.ResolvedModule]]
}

Expand All @@ -49,7 +55,7 @@ type processedFiles struct {
sourceFileMetaDatas map[tspath.Path]ast.SourceFileMetaData
jsxRuntimeImportSpecifiers map[tspath.Path]*jsxRuntimeImportSpecifier
importHelpersImportSpecifiers map[tspath.Path]*ast.Node
libFiles collections.Set[tspath.Path]
libFiles map[tspath.Path]*LibFile
// List of present unsupported extensions
unsupportedExtensions []string
sourceFilesFoundSearchingNodeModules collections.Set[tspath.Path]
Expand Down Expand Up @@ -89,24 +95,26 @@ func processAllProgramFiles(
loader.addProjectReferenceTasks(singleThreaded)
loader.resolver = module.NewResolver(loader.projectReferenceFileMapper.host, compilerOptions, opts.TypingsLocation, opts.ProjectName)

var libs []string
for _, file := range rootFiles {
loader.addRootTask(file, nil)
}

if len(rootFiles) > 0 && compilerOptions.NoLib.IsFalseOrUnknown() {
if compilerOptions.Lib == nil {
name := tsoptions.GetDefaultLibFileName(compilerOptions)
libs = append(libs, loader.pathForLibFile(name))
libFile := loader.pathForLibFile(name)
loader.addRootTask(libFile.path, libFile)
} else {
for _, lib := range compilerOptions.Lib {
if name, ok := tsoptions.GetLibFileName(lib); ok {
libs = append(libs, loader.pathForLibFile(name))
libFile := loader.pathForLibFile(name)
loader.addRootTask(libFile.path, libFile)
}
// !!! error on unknown name
}
}
}

loader.addRootTasks(rootFiles, false)
loader.addRootTasks(libs, true)

if len(rootFiles) > 0 {
loader.addAutomaticTypeDirectiveTasks()
}
Expand All @@ -131,7 +139,7 @@ func processAllProgramFiles(
var importHelpersImportSpecifiers map[tspath.Path]*ast.Node
var unsupportedExtensions []string
var sourceFilesFoundSearchingNodeModules collections.Set[tspath.Path]
var libFileSet collections.Set[tspath.Path]
libFilesMap := make(map[tspath.Path]*LibFile, libFileCount)
fileLoadDiagnostics := &ast.DiagnosticsCollection{}

loader.filesParser.collect(&loader, loader.rootTasks, func(task *parseTask) {
Expand All @@ -149,9 +157,9 @@ func processAllProgramFiles(
missingFiles = append(missingFiles, task.normalizedFilePath)
return
}
if task.isLib {
if task.libFile != nil {
libFiles = append(libFiles, file)
libFileSet.Add(path)
libFilesMap[path] = task.libFile
} else {
files = append(files, file)
}
Expand Down Expand Up @@ -222,7 +230,7 @@ func processAllProgramFiles(
importHelpersImportSpecifiers: importHelpersImportSpecifiers,
unsupportedExtensions: unsupportedExtensions,
sourceFilesFoundSearchingNodeModules: sourceFilesFoundSearchingNodeModules,
libFiles: libFileSet,
libFiles: libFilesMap,
fileLoadDiagnostics: fileLoadDiagnostics,
}
}
Expand All @@ -231,12 +239,10 @@ func (p *fileLoader) toPath(file string) tspath.Path {
return tspath.ToPath(file, p.opts.Host.GetCurrentDirectory(), p.opts.Host.FS().UseCaseSensitiveFileNames())
}

func (p *fileLoader) addRootTasks(files []string, isLib bool) {
for _, fileName := range files {
absPath := tspath.GetNormalizedAbsolutePath(fileName, p.opts.Host.GetCurrentDirectory())
if core.Tristate.IsTrue(p.opts.Config.CompilerOptions().AllowNonTsExtensions) || slices.Contains(p.supportedExtensions, tspath.TryGetExtensionFromPath(absPath)) {
p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: absPath, isLib: isLib, root: true})
}
func (p *fileLoader) addRootTask(fileName string, libFile *LibFile) {
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})
}
}

Expand All @@ -249,7 +255,7 @@ func (p *fileLoader) addAutomaticTypeDirectiveTasks() {
containingDirectory = p.opts.Host.GetCurrentDirectory()
}
containingFileName := tspath.CombinePaths(containingDirectory, module.InferredTypesContainingFile)
p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: containingFileName, isLib: false, isForAutomaticTypeDirective: true})
p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: containingFileName, isForAutomaticTypeDirective: true})
}

func (p *fileLoader) resolveAutomaticTypeDirectives(containingFileName string) (
Expand Down Expand Up @@ -304,12 +310,12 @@ func (p *fileLoader) addProjectReferenceTasks(singleThreaded bool) {
}
if p.opts.canUseProjectReferenceSource() {
for _, fileName := range resolved.FileNames() {
p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: fileName, isLib: false})
p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: fileName})
}
} else {
for outputDts := range resolved.GetOutputDeclarationFileNames() {
if outputDts != "" {
p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: outputDts, isLib: false})
p.rootTasks = append(p.rootTasks, &parseTask{normalizedFilePath: outputDts})
}
}
}
Expand Down Expand Up @@ -405,7 +411,7 @@ func (p *fileLoader) resolveTypeReferenceDirectives(t *parseTask) {
increaseDepth: resolved.IsExternalLibraryImport,
elideOnDepth: false,
isFromExternalLibrary: resolved.IsExternalLibraryImport,
}, false)
}, nil)
}
}

Expand Down Expand Up @@ -496,7 +502,7 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) {
increaseDepth: resolvedModule.IsExternalLibraryImport,
elideOnDepth: isJsFileFromNodeModules,
isFromExternalLibrary: resolvedModule.IsExternalLibraryImport,
}, false)
}, nil)
}
}

Expand All @@ -517,26 +523,28 @@ func (p *fileLoader) createSyntheticImport(text string, file *ast.SourceFile) *a
return externalHelpersModuleReference
}

func (p *fileLoader) pathForLibFile(name string) string {
func (p *fileLoader) pathForLibFile(name string) *LibFile {
if cached, ok := p.pathForLibFileCache.Load(name); ok {
return cached
}

path := tspath.CombinePaths(p.defaultLibraryPath, name)
replaced := false
if p.opts.Config.CompilerOptions().LibReplacement.IsTrue() {
libraryName := getLibraryNameFromLibFileName(name)
resolveFrom := getInferredLibraryNameResolveFrom(p.opts.Config.CompilerOptions(), p.opts.Host.GetCurrentDirectory(), name)
resolution := p.resolver.ResolveModuleName(libraryName, resolveFrom, core.ModuleKindCommonJS, nil)
if resolution.IsResolved() {
path = resolution.ResolvedFileName
replaced = true
p.pathForLibFileResolutions.LoadOrStore(p.toPath(resolveFrom), module.ModeAwareCache[*module.ResolvedModule]{
module.ModeAwareCacheKey{Name: libraryName, Mode: core.ModuleKindCommonJS}: resolution,
})
}
}

path, _ = p.pathForLibFileCache.LoadOrStore(name, path)
return path
libPath, _ := p.pathForLibFileCache.LoadOrStore(name, &LibFile{name, path, replaced})
return libPath
}

func getLibraryNameFromLibFileName(libFileName string) string {
Expand Down
17 changes: 9 additions & 8 deletions internal/compiler/filesparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type parseTask struct {
normalizedFilePath string
path tspath.Path
file *ast.SourceFile
isLib bool
libFile *LibFile
isRedirected bool
subTasks []*parseTask
loaded bool
Expand Down Expand Up @@ -59,7 +59,7 @@ func (t *parseTask) load(loader *fileLoader) {
}

loader.totalFileCount.Add(1)
if t.isLib {
if t.libFile != nil {
loader.libFileCount.Add(1)
}

Expand All @@ -74,7 +74,7 @@ func (t *parseTask) load(loader *fileLoader) {

for _, ref := range file.ReferencedFiles {
resolvedPath := loader.resolveTripleslashPathReference(ref.FileName, file.FileName())
t.addSubTask(resolvedPath, false)
t.addSubTask(resolvedPath, nil)
}

compilerOptions := loader.opts.Config.CompilerOptions()
Expand All @@ -83,7 +83,8 @@ func (t *parseTask) load(loader *fileLoader) {
if compilerOptions.NoLib != core.TSTrue {
for _, lib := range file.LibReferenceDirectives {
if name, ok := tsoptions.GetLibFileName(lib.FileName); ok {
t.addSubTask(resolvedRef{fileName: loader.pathForLibFile(name)}, true)
libFile := loader.pathForLibFile(name)
t.addSubTask(resolvedRef{fileName: libFile.path}, libFile)
}
}
}
Expand All @@ -94,14 +95,14 @@ func (t *parseTask) load(loader *fileLoader) {
func (t *parseTask) redirect(loader *fileLoader, fileName string) {
t.isRedirected = true
// increaseDepth and elideOnDepth are not copied to redirects, otherwise their depth would be double counted.
t.subTasks = []*parseTask{{normalizedFilePath: tspath.NormalizePath(fileName), isLib: t.isLib, fromExternalLibrary: t.fromExternalLibrary}}
t.subTasks = []*parseTask{{normalizedFilePath: tspath.NormalizePath(fileName), libFile: t.libFile, fromExternalLibrary: t.fromExternalLibrary}}
}

func (t *parseTask) loadAutomaticTypeDirectives(loader *fileLoader) {
toParseTypeRefs, typeResolutionsInFile := loader.resolveAutomaticTypeDirectives(t.normalizedFilePath)
t.typeResolutionsInFile = typeResolutionsInFile
for _, typeResolution := range toParseTypeRefs {
t.addSubTask(typeResolution, false)
t.addSubTask(typeResolution, nil)
}
}

Expand All @@ -112,11 +113,11 @@ type resolvedRef struct {
isFromExternalLibrary bool
}

func (t *parseTask) addSubTask(ref resolvedRef, isLib bool) {
func (t *parseTask) addSubTask(ref resolvedRef, libFile *LibFile) {
normalizedFilePath := tspath.NormalizePath(ref.fileName)
subTask := &parseTask{
normalizedFilePath: normalizedFilePath,
isLib: isLib,
libFile: libFile,
increaseDepth: ref.increaseDepth,
elideOnDepth: ref.elideOnDepth,
fromExternalLibrary: ref.isFromExternalLibrary,
Expand Down
10 changes: 9 additions & 1 deletion internal/compiler/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,15 @@ func (p *Program) GetDefaultResolutionModeForFile(sourceFile ast.HasFileName) co
}

func (p *Program) IsSourceFileDefaultLibrary(path tspath.Path) bool {
return p.libFiles.Has(path)
_, ok := p.libFiles[path]
return ok
}

func (p *Program) GetDefaultLibFile(path tspath.Path) *LibFile {
if libFile, ok := p.libFiles[path]; ok {
return libFile
}
return nil
}

func (p *Program) CommonSourceDirectory() string {
Expand Down
2 changes: 1 addition & 1 deletion internal/execute/tsc.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func performIncrementalCompilation(
) CommandLineResult {
host := compiler.NewCachedFSCompilerHost(sys.GetCurrentDirectory(), sys.FS(), sys.DefaultLibraryPath(), extendedConfigCache)
buildInfoReadStart := sys.Now()
oldProgram := incremental.ReadBuildInfoProgram(config, incremental.NewBuildInfoReader(host))
oldProgram := incremental.ReadBuildInfoProgram(config, incremental.NewBuildInfoReader(host), host)
buildInfoReadTime := sys.Now().Sub(buildInfoReadStart)
// todo: cache, statistics, tracing
parseStart := sys.Now()
Expand Down
2 changes: 1 addition & 1 deletion internal/execute/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func createWatcher(sys System, configParseResult *tsoptions.ParsedCommandLine, r

func (w *Watcher) start() {
w.host = compiler.NewCompilerHost(w.sys.GetCurrentDirectory(), w.sys.FS(), w.sys.DefaultLibraryPath(), nil)
w.program = incremental.ReadBuildInfoProgram(w.options, incremental.NewBuildInfoReader(w.host))
w.program = incremental.ReadBuildInfoProgram(w.options, incremental.NewBuildInfoReader(w.host), w.host)

if !w.testing {
watchInterval := 1000 * time.Millisecond
Expand Down
8 changes: 7 additions & 1 deletion internal/incremental/buildinfotosnapshot.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
package incremental

import (
"strings"

"github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/compiler"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
)

func buildInfoToSnapshot(buildInfo *BuildInfo, buildInfoFileName string, config *tsoptions.ParsedCommandLine) *snapshot {
func buildInfoToSnapshot(buildInfo *BuildInfo, buildInfoFileName string, config *tsoptions.ParsedCommandLine, host compiler.CompilerHost) *snapshot {
to := &toSnapshot{
buildInfo: buildInfo,
buildInfoDirectory: tspath.GetDirectoryPath(tspath.GetNormalizedAbsolutePath(buildInfoFileName, config.GetCurrentDirectory())),
filePaths: make([]tspath.Path, 0, len(buildInfo.FileNames)),
filePathSet: make([]*collections.Set[tspath.Path], 0, len(buildInfo.FileIdsList)),
}
to.filePaths = core.Map(buildInfo.FileNames, func(fileName string) tspath.Path {
if !strings.HasPrefix(fileName, ".") {
return tspath.ToPath(tspath.CombinePaths(host.DefaultLibraryPath(), fileName), host.GetCurrentDirectory(), host.FS().UseCaseSensitiveFileNames())
}
return tspath.ToPath(fileName, to.buildInfoDirectory, config.UseCaseSensitiveFileNames())
})
to.filePathSet = core.Map(buildInfo.FileIdsList, func(fileIdList []BuildInfoFileId) *collections.Set[tspath.Path] {
Expand Down
4 changes: 2 additions & 2 deletions internal/incremental/incremental.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func NewBuildInfoReader(
return &buildInfoReader{host: host}
}

func ReadBuildInfoProgram(config *tsoptions.ParsedCommandLine, reader BuildInfoReader) *Program {
func ReadBuildInfoProgram(config *tsoptions.ParsedCommandLine, reader BuildInfoReader, host compiler.CompilerHost) *Program {
buildInfoFileName := config.GetBuildInfoFileName()
if buildInfoFileName == "" {
return nil
Expand All @@ -50,7 +50,7 @@ func ReadBuildInfoProgram(config *tsoptions.ParsedCommandLine, reader BuildInfoR

// Convert to information that can be used to create incremental program
incrementalProgram := &Program{
snapshot: buildInfoToSnapshot(buildInfo, buildInfoFileName, config),
snapshot: buildInfoToSnapshot(buildInfo, buildInfoFileName, config, host),
}
return incrementalProgram
}
10 changes: 8 additions & 2 deletions internal/incremental/snapshottobuildinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ func (t *toBuildInfo) relativeToBuildInfo(path string) string {
func (t *toBuildInfo) toFileId(path tspath.Path) BuildInfoFileId {
fileId := t.fileNameToFileId[string(path)]
if fileId == 0 {
t.buildInfo.FileNames = append(t.buildInfo.FileNames, t.relativeToBuildInfo(string(path)))
if libFile := t.program.GetDefaultLibFile(path); libFile != nil && !libFile.Replaced {
t.buildInfo.FileNames = append(t.buildInfo.FileNames, libFile.Name)
} else {
t.buildInfo.FileNames = append(t.buildInfo.FileNames, t.relativeToBuildInfo(string(path)))
}
fileId = BuildInfoFileId(len(t.buildInfo.FileNames))
t.fileNameToFileId[string(path)] = fileId
}
Expand Down Expand Up @@ -176,7 +180,9 @@ func (t *toBuildInfo) setFileInfoAndEmitSignatures() {
fileId := t.toFileId(file.Path())
// tryAddRoot(key, fileId);
if t.buildInfo.FileNames[fileId-1] != t.relativeToBuildInfo(string(file.Path())) {
panic(fmt.Sprintf("File name at index %d does not match expected relative path: %s != %s", fileId-1, t.buildInfo.FileNames[fileId-1], t.relativeToBuildInfo(string(file.Path()))))
if libFile := t.program.GetDefaultLibFile(file.Path()); libFile == nil || libFile.Replaced || t.buildInfo.FileNames[fileId-1] != libFile.Name {
panic(fmt.Sprintf("File name at index %d does not match expected relative path or libName: %s != %s", fileId-1, t.buildInfo.FileNames[fileId-1], t.relativeToBuildInfo(string(file.Path()))))
}
}
if t.snapshot.options.Composite.IsTrue() {
if !ast.IsJsonSourceFile(file) && t.program.SourceFileMayBeEmitted(file, false) {
Expand Down
Loading
Loading