diff --git a/cmd/tsgo/sys.go b/cmd/tsgo/sys.go
index 6f28371e77..e5b2b8d569 100644
--- a/cmd/tsgo/sys.go
+++ b/cmd/tsgo/sys.go
@@ -7,7 +7,7 @@ import (
"time"
"github.com/microsoft/typescript-go/internal/bundled"
- "github.com/microsoft/typescript-go/internal/execute"
+ "github.com/microsoft/typescript-go/internal/execute/tsc"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
@@ -63,7 +63,7 @@ func newSystem() *osSys {
cwd, err := os.Getwd()
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting current directory: %v\n", err)
- os.Exit(int(execute.ExitStatusInvalidProject_OutputsSkipped))
+ os.Exit(int(tsc.ExitStatusInvalidProject_OutputsSkipped))
}
return &osSys{
diff --git a/internal/api/server.go b/internal/api/server.go
index 7d0dcc1f0a..28bb965917 100644
--- a/internal/api/server.go
+++ b/internal/api/server.go
@@ -8,6 +8,7 @@ import (
"io"
"strconv"
"sync"
+ "time"
"github.com/go-json-experiment/json"
"github.com/microsoft/typescript-go/internal/bundled"
@@ -472,3 +473,8 @@ func (s *Server) Stat(path string) vfs.FileInfo {
func (s *Server) Remove(path string) error {
panic("unimplemented")
}
+
+// Chtimes implements vfs.FS.
+func (s *Server) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ panic("unimplemented")
+}
diff --git a/internal/bundled/embed.go b/internal/bundled/embed.go
index 82ba6f9634..36c00137b2 100644
--- a/internal/bundled/embed.go
+++ b/internal/bundled/embed.go
@@ -161,6 +161,13 @@ func (vfs *wrappedFS) Remove(path string) error {
return vfs.fs.Remove(path)
}
+func (vfs *wrappedFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ if _, ok := splitPath(path); ok {
+ panic("cannot change times on embedded file system")
+ }
+ return vfs.fs.Chtimes(path, aTime, mTime)
+}
+
type fileInfo struct {
mode fs.FileMode
name string
diff --git a/internal/checker/checker.go b/internal/checker/checker.go
index 1d164bcce3..397ad9cbef 100644
--- a/internal/checker/checker.go
+++ b/internal/checker/checker.go
@@ -540,7 +540,7 @@ type Program interface {
SourceFileMayBeEmitted(sourceFile *ast.SourceFile, forceDtsEmit bool) bool
IsSourceFromProjectReference(path tspath.Path) bool
IsSourceFileDefaultLibrary(path tspath.Path) bool
- GetSourceAndProjectReference(path tspath.Path) *tsoptions.SourceAndProjectReference
+ GetProjectReferenceFromOutputDts(path tspath.Path) *tsoptions.SourceOutputAndProjectReference
GetRedirectForResolution(file ast.HasFileName) *tsoptions.ParsedCommandLine
CommonSourceDirectory() string
}
@@ -6483,7 +6483,7 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) {
}
if c.compilerOptions.VerbatimModuleSyntax.IsTrue() && !ast.IsTypeOnlyImportOrExportDeclaration(node) && node.Flags&ast.NodeFlagsAmbient == 0 && targetFlags&ast.SymbolFlagsConstEnum != 0 {
constEnumDeclaration := target.ValueDeclaration
- redirect := c.program.GetSourceAndProjectReference(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
+ redirect := c.program.GetProjectReferenceFromOutputDts(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && (redirect == nil || !redirect.Resolved.CompilerOptions().ShouldPreserveConstEnums()) {
c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
}
@@ -7204,7 +7204,7 @@ func (c *Checker) checkConstEnumAccess(node *ast.Node, t *Type) {
if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, ast.GetFirstIdentifier(node).Text(), ast.SymbolFlagsAlias, nil, false, true) == nil {
debug.Assert(t.symbol.Flags&ast.SymbolFlagsConstEnum != 0)
constEnumDeclaration := t.symbol.ValueDeclaration
- redirect := c.program.GetSourceAndProjectReference(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
+ redirect := c.program.GetProjectReferenceFromOutputDts(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && !ast.IsValidTypeOnlyAliasUseSite(node) && (redirect == nil || !redirect.Resolved.CompilerOptions().ShouldPreserveConstEnums()) {
c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
}
@@ -14636,7 +14636,7 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
}
var message *diagnostics.Message
- if overrideHost != nil && overrideHost.Kind == ast.KindImportDeclaration && overrideHost.AsImportDeclaration().ImportClause.IsTypeOnly() {
+ if overrideHost != nil && overrideHost.Kind == ast.KindImportDeclaration && overrideHost.AsImportDeclaration().ImportClause != nil && overrideHost.AsImportDeclaration().ImportClause.IsTypeOnly() {
message = diagnostics.Type_only_import_of_an_ECMAScript_module_from_a_CommonJS_module_must_have_a_resolution_mode_attribute
} else if overrideHost != nil && overrideHost.Kind == ast.KindImportType {
message = diagnostics.Type_import_of_an_ECMAScript_module_from_a_CommonJS_module_must_have_a_resolution_mode_attribute
@@ -14689,7 +14689,7 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
if moduleNotFoundError != nil {
// See if this was possibly a projectReference redirect
if resolvedModule.IsResolved() {
- redirect := c.program.GetOutputAndProjectReference(tspath.ToPath(resolvedModule.ResolvedFileName, c.program.GetCurrentDirectory(), c.program.UseCaseSensitiveFileNames()))
+ redirect := c.program.GetProjectReferenceFromSource(tspath.ToPath(resolvedModule.ResolvedFileName, c.program.GetCurrentDirectory(), c.program.UseCaseSensitiveFileNames()))
if redirect != nil && redirect.OutputDts != "" {
c.error(
errorNode,
diff --git a/internal/collections/syncset.go b/internal/collections/syncset.go
index 1b9be611c0..c933d6ec90 100644
--- a/internal/collections/syncset.go
+++ b/internal/collections/syncset.go
@@ -11,8 +11,13 @@ func (s *SyncSet[T]) Has(key T) bool {
return ok
}
+func (s *SyncSet[T]) AddIfAbsent(key T) bool {
+ _, loaded := s.m.LoadOrStore(key, struct{}{})
+ return !loaded
+}
+
func (s *SyncSet[T]) Add(key T) {
- s.m.Store(key, struct{}{})
+ s.AddIfAbsent(key)
}
func (s *SyncSet[T]) Delete(key T) {
diff --git a/internal/compiler/emitHost.go b/internal/compiler/emitHost.go
index cf6f68dee6..fcc0406342 100644
--- a/internal/compiler/emitHost.go
+++ b/internal/compiler/emitHost.go
@@ -78,8 +78,8 @@ func (host *emitHost) GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFi
return host.program.GetSourceOfProjectReferenceIfOutputIncluded(file)
}
-func (host *emitHost) GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
- return host.program.GetOutputAndProjectReference(path)
+func (host *emitHost) GetProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
+ return host.program.GetProjectReferenceFromSource(path)
}
func (host *emitHost) GetRedirectTargets(path tspath.Path) []string {
diff --git a/internal/compiler/emitter.go b/internal/compiler/emitter.go
index 2b15feb2ff..6e6cc023bc 100644
--- a/internal/compiler/emitter.go
+++ b/internal/compiler/emitter.go
@@ -43,9 +43,6 @@ type emitter struct {
}
func (e *emitter) emit() {
- if e.host.Options().ListEmittedFiles.IsTrue() {
- e.emitResult.EmittedFiles = []string{}
- }
// !!! tracing
e.emitJSFile(e.sourceFile, e.paths.JsFilePath(), e.paths.SourceMapFilePath())
e.emitDeclarationFile(e.sourceFile, e.paths.DeclarationFilePath(), e.paths.DeclarationMapPath())
@@ -268,7 +265,7 @@ func (e *emitter) printSourceFile(jsFilePath string, sourceMapFilePath string, s
err := e.host.WriteFile(sourceMapFilePath, sourceMap, false /*writeByteOrderMark*/)
if err != nil {
e.emitterDiagnostics.Add(ast.NewCompilerDiagnostic(diagnostics.Could_not_write_file_0_Colon_1, jsFilePath, err.Error()))
- } else if e.emitResult.EmittedFiles != nil {
+ } else {
e.emitResult.EmittedFiles = append(e.emitResult.EmittedFiles, sourceMapFilePath)
}
}
@@ -292,7 +289,7 @@ func (e *emitter) printSourceFile(jsFilePath string, sourceMapFilePath string, s
}
if err != nil {
e.emitterDiagnostics.Add(ast.NewCompilerDiagnostic(diagnostics.Could_not_write_file_0_Colon_1, jsFilePath, err.Error()))
- } else if e.emitResult.EmittedFiles != nil && !skippedDtsWrite {
+ } else if !skippedDtsWrite {
e.emitResult.EmittedFiles = append(e.emitResult.EmittedFiles, jsFilePath)
}
@@ -391,7 +388,7 @@ func (e *emitter) getSourceMappingURL(mapOptions *core.CompilerOptions, sourceMa
type SourceFileMayBeEmittedHost interface {
Options() *core.CompilerOptions
- GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference
+ GetProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference
IsSourceFileFromExternalLibrary(file *ast.SourceFile) bool
GetCurrentDirectory() string
UseCaseSensitiveFileNames() bool
@@ -424,7 +421,7 @@ func sourceFileMayBeEmitted(sourceFile *ast.SourceFile, host SourceFileMayBeEmit
// Check other conditions for file emit
// Source files from referenced projects are not emitted
- if host.GetOutputAndProjectReference(sourceFile.Path()) != nil {
+ if host.GetProjectReferenceFromSource(sourceFile.Path()) != nil {
return false
}
diff --git a/internal/compiler/fileInclude.go b/internal/compiler/fileInclude.go
index 2e16f018df..68687e5e03 100644
--- a/internal/compiler/fileInclude.go
+++ b/internal/compiler/fileInclude.go
@@ -8,6 +8,7 @@ import (
"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/scanner"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
)
@@ -57,7 +58,11 @@ type referenceFileLocation struct {
func (r *referenceFileLocation) text() string {
if r.node != nil {
- return r.node.Text()
+ if !ast.NodeIsSynthesized(r.node) {
+ return r.file.Text()[scanner.SkipTrivia(r.file.Text(), r.node.Loc.Pos()):r.node.End()]
+ } else {
+ return fmt.Sprintf(`"%s"`, r.node.Text())
+ }
} else {
return r.file.Text()[r.ref.Pos():r.ref.End()]
}
diff --git a/internal/compiler/fileloader.go b/internal/compiler/fileloader.go
index 1df4c404ec..d18761ee29 100644
--- a/internal/compiler/fileloader.go
+++ b/internal/compiler/fileloader.go
@@ -143,7 +143,10 @@ func processAllProgramFiles(
filesByPath := make(map[tspath.Path]*ast.SourceFile, totalFileCount)
loader.includeProcessor.fileIncludeReasons = make(map[tspath.Path][]*fileIncludeReason, totalFileCount)
- outputFileToProjectReferenceSource := make(map[tspath.Path]string, totalFileCount)
+ var outputFileToProjectReferenceSource map[tspath.Path]string
+ if !opts.canUseProjectReferenceSource() {
+ 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)
@@ -454,9 +457,9 @@ func (p *fileLoader) resolveTypeReferenceDirectives(t *parseTask) {
typeResolutionsInFile := make(module.ModeAwareCache[*module.ResolvedTypeReferenceDirective], len(file.TypeReferenceDirectives))
var typeResolutionsTrace []string
for index, ref := range file.TypeReferenceDirectives {
- redirect := p.projectReferenceFileMapper.getRedirectForResolution(file)
+ redirect, fileName := 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)
+ resolved, trace := p.resolver.ResolveTypeReferenceDirective(ref.FileName, fileName, resolutionMode, redirect)
typeResolutionsInFile[module.ModeAwareCacheKey{Name: ref.FileName, Mode: resolutionMode}] = resolved
includeReason := &fileIncludeReason{
kind: fileIncludeKindTypeReferenceDirective,
@@ -498,7 +501,7 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) {
isJavaScriptFile := ast.IsSourceFileJS(file)
isExternalModuleFile := ast.IsExternalModule(file)
- redirect := p.projectReferenceFileMapper.getRedirectForResolution(file)
+ redirect, fileName := p.projectReferenceFileMapper.getRedirectForResolution(file)
optionsForFile := module.GetCompilerOptionsWithRedirect(p.opts.Config.CompilerOptions(), redirect)
if isJavaScriptFile || (!file.IsDeclarationFile && (optionsForFile.GetIsolatedModules() || isExternalModuleFile)) {
if optionsForFile.ImportHelpers.IsTrue() {
@@ -539,7 +542,7 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) {
}
mode := getModeForUsageLocation(file.FileName(), meta, entry, optionsForFile)
- resolvedModule, trace := p.resolver.ResolveModuleName(moduleName, file.FileName(), mode, redirect)
+ resolvedModule, trace := p.resolver.ResolveModuleName(moduleName, fileName, mode, redirect)
resolutionsInFile[module.ModeAwareCacheKey{Name: moduleName, Mode: mode}] = resolvedModule
resolutionsTrace = append(resolutionsTrace, trace...)
@@ -550,7 +553,7 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) {
resolvedFileName := resolvedModule.ResolvedFileName
isFromNodeModulesSearch := resolvedModule.IsExternalLibraryImport
// Don't treat redirected files as JS files.
- isJsFile := !tspath.FileExtensionIsOneOf(resolvedFileName, tspath.SupportedTSExtensionsWithJsonFlat) && p.projectReferenceFileMapper.getRedirectForResolution(ast.NewHasFileName(resolvedFileName, p.toPath(resolvedFileName))) == nil
+ isJsFile := !tspath.FileExtensionIsOneOf(resolvedFileName, tspath.SupportedTSExtensionsWithJsonFlat) && p.projectReferenceFileMapper.getRedirectParsedCommandLineForResolution(ast.NewHasFileName(resolvedFileName, p.toPath(resolvedFileName))) == nil
isJsFileFromNodeModules := isFromNodeModulesSearch && isJsFile && strings.Contains(resolvedFileName, "/node_modules/")
// add file to program only if:
@@ -610,19 +613,19 @@ func (p *fileLoader) pathForLibFile(name string) *LibFile {
path := tspath.CombinePaths(p.defaultLibraryPath, name)
replaced := false
- if p.opts.Config.CompilerOptions().LibReplacement.IsTrue() {
+ if p.opts.Config.CompilerOptions().LibReplacement.IsTrue() && name != "lib.d.ts" {
libraryName := getLibraryNameFromLibFileName(name)
resolveFrom := getInferredLibraryNameResolveFrom(p.opts.Config.CompilerOptions(), p.opts.Host.GetCurrentDirectory(), name)
resolution, trace := p.resolver.ResolveModuleName(libraryName, resolveFrom, core.ModuleKindCommonJS, nil)
if resolution.IsResolved() {
path = resolution.ResolvedFileName
replaced = true
- p.pathForLibFileResolutions.LoadOrStore(p.toPath(resolveFrom), &libResolution{
- libraryName: libraryName,
- resolution: resolution,
- trace: trace,
- })
}
+ p.pathForLibFileResolutions.LoadOrStore(p.toPath(resolveFrom), &libResolution{
+ libraryName: libraryName,
+ resolution: resolution,
+ trace: trace,
+ })
}
libPath, _ := p.pathForLibFileCache.LoadOrStore(name, &LibFile{name, path, replaced})
diff --git a/internal/compiler/processingDiagnostic.go b/internal/compiler/processingDiagnostic.go
index 4fde4a9caf..83bac967ab 100644
--- a/internal/compiler/processingDiagnostic.go
+++ b/internal/compiler/processingDiagnostic.go
@@ -67,7 +67,7 @@ func (d *processingDiagnostic) toDiagnostic(program *Program) *ast.Diagnostic {
func (d *processingDiagnostic) createDiagnosticExplainingFile(program *Program) *ast.Diagnostic {
diag := d.asIncludeExplainingDiagnostic()
- var chain []*ast.Diagnostic
+ var includeDetails []*ast.Diagnostic
var relatedInfo []*ast.Diagnostic
var redirectInfo []*ast.Diagnostic
var preferredLocation *fileIncludeReason
@@ -90,7 +90,7 @@ func (d *processingDiagnostic) createDiagnosticExplainingFile(program *Program)
if !seenReasons.AddIfAbsent(includeReason) {
return
}
- chain = append(chain, includeReason.toDiagnostic(program, false))
+ includeDetails = append(includeDetails, includeReason.toDiagnostic(program, false))
processRelatedInfo(includeReason)
}
@@ -98,7 +98,7 @@ func (d *processingDiagnostic) createDiagnosticExplainingFile(program *Program)
if diag.file != "" {
reasons := program.includeProcessor.fileIncludeReasons[diag.file]
- chain = make([]*ast.Diagnostic, 0, len(reasons))
+ includeDetails = make([]*ast.Diagnostic, 0, len(reasons))
for _, reason := range reasons {
processInclude(reason)
}
@@ -107,9 +107,10 @@ func (d *processingDiagnostic) createDiagnosticExplainingFile(program *Program)
if diag.diagnosticReason != nil {
processInclude(diag.diagnosticReason)
}
- if chain != nil && (preferredLocation == nil || seenReasons.Len() != 1) {
+ var chain []*ast.Diagnostic
+ if includeDetails != nil && (preferredLocation == nil || seenReasons.Len() != 1) {
fileReason := ast.NewCompilerDiagnostic(diagnostics.The_file_is_in_the_program_because_Colon)
- fileReason.SetMessageChain(chain)
+ fileReason.SetMessageChain(includeDetails)
chain = []*ast.Diagnostic{fileReason}
}
if redirectInfo != nil {
diff --git a/internal/compiler/program.go b/internal/compiler/program.go
index 4f0f201134..4769f82868 100644
--- a/internal/compiler/program.go
+++ b/internal/compiler/program.go
@@ -113,9 +113,9 @@ func (p *Program) GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFileNa
return file.FileName()
}
-// GetOutputAndProjectReference implements checker.Program.
-func (p *Program) GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
- return p.projectReferenceFileMapper.getOutputAndProjectReference(path)
+// GetProjectReferenceFromSource implements checker.Program.
+func (p *Program) GetProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
+ return p.projectReferenceFileMapper.getProjectReferenceFromSource(path)
}
// IsSourceFromProjectReference implements checker.Program.
@@ -123,8 +123,8 @@ func (p *Program) IsSourceFromProjectReference(path tspath.Path) bool {
return p.projectReferenceFileMapper.isSourceFromProjectReference(path)
}
-func (p *Program) GetSourceAndProjectReference(path tspath.Path) *tsoptions.SourceAndProjectReference {
- return p.projectReferenceFileMapper.getSourceAndProjectReference(path)
+func (p *Program) GetProjectReferenceFromOutputDts(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
+ return p.projectReferenceFileMapper.getProjectReferenceFromOutputDts(path)
}
func (p *Program) GetResolvedProjectReferenceFor(path tspath.Path) (*tsoptions.ParsedCommandLine, bool) {
@@ -132,7 +132,8 @@ func (p *Program) GetResolvedProjectReferenceFor(path tspath.Path) (*tsoptions.P
}
func (p *Program) GetRedirectForResolution(file ast.HasFileName) *tsoptions.ParsedCommandLine {
- return p.projectReferenceFileMapper.getRedirectForResolution(file)
+ redirect, _ := p.projectReferenceFileMapper.getRedirectForResolution(file)
+ return redirect
}
func (p *Program) GetParseFileRedirect(fileName string) string {
@@ -270,6 +271,7 @@ func equalCheckJSDirectives(d1 *ast.CheckJsDirective, d2 *ast.CheckJsDirective)
func (p *Program) SourceFiles() []*ast.SourceFile { return p.files }
func (p *Program) Options() *core.CompilerOptions { return p.opts.Config.CompilerOptions() }
+func (p *Program) GetRootFileNames() []string { return p.opts.Config.FileNames() }
func (p *Program) Host() CompilerHost { return p.opts.Host }
func (p *Program) GetConfigFileParsingDiagnostics() []*ast.Diagnostic {
return slices.Clip(p.opts.Config.GetConfigFileParsingDiagnostics())
@@ -1268,11 +1270,10 @@ func (p *Program) CommonSourceDirectory() string {
}
type WriteFileData struct {
- SourceMapUrlPos int
- BuildInfo any
- Diagnostics []*ast.Diagnostic
- DiffersOnlyInMap bool
- SkippedDtsWrite bool
+ SourceMapUrlPos int
+ BuildInfo any
+ Diagnostics []*ast.Diagnostic
+ SkippedDtsWrite bool
}
type EmitOptions struct {
@@ -1364,9 +1365,7 @@ func CombineEmitResults(results []*EmitResult) *EmitResult {
result.EmitSkipped = true
}
result.Diagnostics = append(result.Diagnostics, emitResult.Diagnostics...)
- if emitResult.EmittedFiles != nil {
- result.EmittedFiles = append(result.EmittedFiles, emitResult.EmittedFiles...)
- }
+ result.EmittedFiles = append(result.EmittedFiles, emitResult.EmittedFiles...)
if emitResult.SourceMaps != nil {
result.SourceMaps = append(result.SourceMaps, emitResult.SourceMaps...)
}
diff --git a/internal/compiler/projectreferencedtsfakinghost.go b/internal/compiler/projectreferencedtsfakinghost.go
index 3bac411dad..916dce2225 100644
--- a/internal/compiler/projectreferencedtsfakinghost.go
+++ b/internal/compiler/projectreferencedtsfakinghost.go
@@ -2,6 +2,7 @@ package compiler
import (
"strings"
+ "time"
"github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/core"
@@ -82,6 +83,11 @@ func (fs *projectReferenceDtsFakingVfs) Remove(path string) error {
panic("should not be called by resolver")
}
+// Chtimes implements vfs.FS.
+func (fs *projectReferenceDtsFakingVfs) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ panic("should not be called by resolver")
+}
+
// DirectoryExists implements vfs.FS.
func (fs *projectReferenceDtsFakingVfs) DirectoryExists(path string) bool {
if fs.projectReferenceFileMapper.opts.Host.FS().DirectoryExists(path) {
@@ -197,7 +203,7 @@ func (fs *projectReferenceDtsFakingVfs) fileOrDirectoryExistsUsingSource(fileOrD
}
func (fs *projectReferenceDtsFakingVfs) fileExistsIfProjectReferenceDts(file string) core.Tristate {
- source := fs.projectReferenceFileMapper.getSourceAndProjectReference(fs.toPath(file))
+ source := fs.projectReferenceFileMapper.getProjectReferenceFromOutputDts(fs.toPath(file))
if source != nil {
return core.IfElse(fs.projectReferenceFileMapper.opts.Host.FS().FileExists(source.Source), core.TSTrue, core.TSFalse)
}
diff --git a/internal/compiler/projectreferencefilemapper.go b/internal/compiler/projectreferencefilemapper.go
index f8bd36e651..17649ec3e0 100644
--- a/internal/compiler/projectreferencefilemapper.go
+++ b/internal/compiler/projectreferencefilemapper.go
@@ -16,19 +16,19 @@ type projectReferenceFileMapper struct {
host module.ResolutionHost
loader *fileLoader // Only present during populating the mapper and parsing, released after that
- configToProjectReference map[tspath.Path]*tsoptions.ParsedCommandLine // All the resolved references needed
- referencesInConfigFile map[tspath.Path][]tspath.Path // Map of config file to its references
- sourceToOutput map[tspath.Path]*tsoptions.OutputDtsAndProjectReference
- outputDtsToSource map[tspath.Path]*tsoptions.SourceAndProjectReference
+ configToProjectReference map[tspath.Path]*tsoptions.ParsedCommandLine // All the resolved references needed
+ referencesInConfigFile map[tspath.Path][]tspath.Path // Map of config file to its references
+ sourceToProjectReference map[tspath.Path]*tsoptions.SourceOutputAndProjectReference
+ outputDtsToProjectReference map[tspath.Path]*tsoptions.SourceOutputAndProjectReference
// Store all the realpath from dts in node_modules to source file from project reference needed during parsing so it can be used later
- realpathDtsToSource collections.SyncMap[tspath.Path, *tsoptions.SourceAndProjectReference]
+ realpathDtsToSource collections.SyncMap[tspath.Path, *tsoptions.SourceOutputAndProjectReference]
}
func (mapper *projectReferenceFileMapper) getParseFileRedirect(file ast.HasFileName) string {
if mapper.opts.canUseProjectReferenceSource() {
// Map to source file from project reference
- source := mapper.getSourceAndProjectReference(file.Path())
+ source := mapper.getProjectReferenceFromOutputDts(file.Path())
if source == nil {
source = mapper.getSourceToDtsIfSymlink(file)
}
@@ -37,7 +37,7 @@ func (mapper *projectReferenceFileMapper) getParseFileRedirect(file ast.HasFileN
}
} else {
// Map to dts file from project reference
- output := mapper.getOutputAndProjectReference(file.Path())
+ output := mapper.getProjectReferenceFromSource(file.Path())
if output != nil && output.OutputDts != "" {
return output.OutputDts
}
@@ -58,42 +58,47 @@ func (mapper *projectReferenceFileMapper) getResolvedProjectReferences() []*tsop
return result
}
-func (mapper *projectReferenceFileMapper) getOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
- return mapper.sourceToOutput[path]
+func (mapper *projectReferenceFileMapper) getProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
+ return mapper.sourceToProjectReference[path]
}
-func (mapper *projectReferenceFileMapper) getSourceAndProjectReference(path tspath.Path) *tsoptions.SourceAndProjectReference {
- return mapper.outputDtsToSource[path]
+func (mapper *projectReferenceFileMapper) getProjectReferenceFromOutputDts(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
+ return mapper.outputDtsToProjectReference[path]
}
func (mapper *projectReferenceFileMapper) isSourceFromProjectReference(path tspath.Path) bool {
- return mapper.opts.canUseProjectReferenceSource() && mapper.getOutputAndProjectReference(path) != nil
+ return mapper.opts.canUseProjectReferenceSource() && mapper.getProjectReferenceFromSource(path) != nil
}
func (mapper *projectReferenceFileMapper) getCompilerOptionsForFile(file ast.HasFileName) *core.CompilerOptions {
- redirect := mapper.getRedirectForResolution(file)
+ redirect := mapper.getRedirectParsedCommandLineForResolution(file)
return module.GetCompilerOptionsWithRedirect(mapper.opts.Config.CompilerOptions(), redirect)
}
-func (mapper *projectReferenceFileMapper) getRedirectForResolution(file ast.HasFileName) *tsoptions.ParsedCommandLine {
+func (mapper *projectReferenceFileMapper) getRedirectParsedCommandLineForResolution(file ast.HasFileName) *tsoptions.ParsedCommandLine {
+ redirect, _ := mapper.getRedirectForResolution(file)
+ return redirect
+}
+
+func (mapper *projectReferenceFileMapper) getRedirectForResolution(file ast.HasFileName) (*tsoptions.ParsedCommandLine, string) {
path := file.Path()
// Check if outputdts of source file from project reference
- output := mapper.getOutputAndProjectReference(path)
+ output := mapper.getProjectReferenceFromSource(path)
if output != nil {
- return output.Resolved
+ return output.Resolved, output.Source
}
// Source file from project reference
- resultFromDts := mapper.getSourceAndProjectReference(path)
+ resultFromDts := mapper.getProjectReferenceFromOutputDts(path)
if resultFromDts != nil {
- return resultFromDts.Resolved
+ return resultFromDts.Resolved, resultFromDts.Source
}
realpathDtsToSource := mapper.getSourceToDtsIfSymlink(file)
if realpathDtsToSource != nil {
- return realpathDtsToSource.Resolved
+ return realpathDtsToSource.Resolved, realpathDtsToSource.Source
}
- return nil
+ return nil, file.FileName()
}
func (mapper *projectReferenceFileMapper) getResolvedReferenceFor(path tspath.Path) (*tsoptions.ParsedCommandLine, bool) {
@@ -129,7 +134,7 @@ func (mapper *projectReferenceFileMapper) forEachResolvedReferenceWorker(
}
}
-func (mapper *projectReferenceFileMapper) getSourceToDtsIfSymlink(file ast.HasFileName) *tsoptions.SourceAndProjectReference {
+func (mapper *projectReferenceFileMapper) getSourceToDtsIfSymlink(file ast.HasFileName) *tsoptions.SourceOutputAndProjectReference {
// If preserveSymlinks is true, module resolution wont jump the symlink
// but the resolved real path may be the .d.ts from project reference
// Note:: Currently we try the real path only if the
@@ -148,7 +153,7 @@ func (mapper *projectReferenceFileMapper) getSourceToDtsIfSymlink(file ast.HasFi
if realDeclarationPath == path {
mapper.realpathDtsToSource.Store(path, nil)
} else {
- realpathDtsToSource := mapper.getSourceAndProjectReference(realDeclarationPath)
+ realpathDtsToSource := mapper.getProjectReferenceFromOutputDts(realDeclarationPath)
if realpathDtsToSource != nil {
mapper.realpathDtsToSource.Store(path, realpathDtsToSource)
return realpathDtsToSource
diff --git a/internal/compiler/projectreferenceparser.go b/internal/compiler/projectreferenceparser.go
index 8943b1805d..e829e3c11c 100644
--- a/internal/compiler/projectreferenceparser.go
+++ b/internal/compiler/projectreferenceparser.go
@@ -18,7 +18,7 @@ func (t *projectReferenceParseTask) parse(projectReferenceParser *projectReferen
if t.resolved == nil {
return
}
- if t.resolved.SourceToOutput() == nil {
+ if t.resolved.SourceToProjectReference() == nil {
projectReferenceParser.wg.Queue(func() {
t.resolved.ParseInputOutputNames()
})
@@ -68,10 +68,10 @@ func (p *projectReferenceParser) initMapper(tasks []*projectReferenceParseTask)
totalReferences := p.tasksByFileName.Size() + 1
p.loader.projectReferenceFileMapper.configToProjectReference = make(map[tspath.Path]*tsoptions.ParsedCommandLine, totalReferences)
p.loader.projectReferenceFileMapper.referencesInConfigFile = make(map[tspath.Path][]tspath.Path, totalReferences)
- p.loader.projectReferenceFileMapper.sourceToOutput = make(map[tspath.Path]*tsoptions.OutputDtsAndProjectReference)
- p.loader.projectReferenceFileMapper.outputDtsToSource = make(map[tspath.Path]*tsoptions.SourceAndProjectReference)
+ p.loader.projectReferenceFileMapper.sourceToProjectReference = make(map[tspath.Path]*tsoptions.SourceOutputAndProjectReference)
+ p.loader.projectReferenceFileMapper.outputDtsToProjectReference = make(map[tspath.Path]*tsoptions.SourceOutputAndProjectReference)
p.loader.projectReferenceFileMapper.referencesInConfigFile[p.loader.opts.Config.ConfigFile.SourceFile.Path()] = p.initMapperWorker(tasks, &collections.Set[*projectReferenceParseTask]{})
- if p.loader.projectReferenceFileMapper.opts.canUseProjectReferenceSource() && len(p.loader.projectReferenceFileMapper.outputDtsToSource) != 0 {
+ if p.loader.projectReferenceFileMapper.opts.canUseProjectReferenceSource() && len(p.loader.projectReferenceFileMapper.outputDtsToProjectReference) != 0 {
p.loader.projectReferenceFileMapper.host = newProjectReferenceDtsFakingHost(p.loader)
}
}
@@ -95,11 +95,11 @@ func (p *projectReferenceParser) initMapperWorker(tasks []*projectReferenceParse
if task.resolved == nil || p.loader.projectReferenceFileMapper.opts.Config.ConfigFile == task.resolved.ConfigFile {
continue
}
- for key, value := range task.resolved.SourceToOutput() {
- p.loader.projectReferenceFileMapper.sourceToOutput[key] = value
+ for key, value := range task.resolved.SourceToProjectReference() {
+ p.loader.projectReferenceFileMapper.sourceToProjectReference[key] = value
}
- for key, value := range task.resolved.OutputDtsToSource() {
- p.loader.projectReferenceFileMapper.outputDtsToSource[key] = value
+ for key, value := range task.resolved.OutputDtsToProjectReference() {
+ p.loader.projectReferenceFileMapper.outputDtsToProjectReference[key] = value
}
if p.loader.projectReferenceFileMapper.opts.canUseProjectReferenceSource() {
declDir := task.resolved.CompilerOptions().DeclarationDir
diff --git a/internal/core/buildoptions.go b/internal/core/buildoptions.go
new file mode 100644
index 0000000000..c7cde7504f
--- /dev/null
+++ b/internal/core/buildoptions.go
@@ -0,0 +1,15 @@
+package core
+
+type BuildOptions struct {
+ _ noCopy
+
+ Dry Tristate `json:"dry,omitzero"`
+ Force Tristate `json:"force,omitzero"`
+ Verbose Tristate `json:"verbose,omitzero"`
+ StopBuildOnErrors Tristate `json:"stopBuildOnErrors,omitzero"`
+
+ // CompilerOptions are not parsed here and will be available on ParsedBuildCommandLine
+
+ // Internal fields
+ Clean Tristate `json:"clean,omitzero"`
+}
diff --git a/internal/core/compileroptions.go b/internal/core/compileroptions.go
index 6fa6f5cfd5..ffca3d6c3d 100644
--- a/internal/core/compileroptions.go
+++ b/internal/core/compileroptions.go
@@ -26,7 +26,6 @@ type CompilerOptions struct {
AllowUnusedLabels Tristate `json:"allowUnusedLabels,omitzero"`
AssumeChangesOnlyAffectDirectDependencies Tristate `json:"assumeChangesOnlyAffectDirectDependencies,omitzero"`
AlwaysStrict Tristate `json:"alwaysStrict,omitzero"`
- Build Tristate `json:"build,omitzero"`
CheckJs Tristate `json:"checkJs,omitzero"`
CustomConditions []string `json:"customConditions,omitzero"`
Composite Tristate `json:"composite,omitzero"`
@@ -142,7 +141,7 @@ type CompilerOptions struct {
Version Tristate `json:"version,omitzero"`
Watch Tristate `json:"watch,omitzero"`
ShowConfig Tristate `json:"showConfig,omitzero"`
- TscBuild Tristate `json:"tscBuild,omitzero"`
+ Build Tristate `json:"build,omitzero"`
Help Tristate `json:"help,omitzero"`
All Tristate `json:"all,omitzero"`
diff --git a/internal/core/projectreference.go b/internal/core/projectreference.go
index ded897f4b6..d5dcf5a78f 100644
--- a/internal/core/projectreference.go
+++ b/internal/core/projectreference.go
@@ -9,10 +9,10 @@ type ProjectReference struct {
}
func ResolveProjectReferencePath(ref *ProjectReference) string {
- return resolveConfigFileNameOfProjectReference(ref.Path)
+ return ResolveConfigFileNameOfProjectReference(ref.Path)
}
-func resolveConfigFileNameOfProjectReference(path string) string {
+func ResolveConfigFileNameOfProjectReference(path string) string {
if tspath.FileExtensionIs(path, tspath.ExtensionJson) {
return path
}
diff --git a/internal/diagnostics/diagnostics_generated.go b/internal/diagnostics/diagnostics_generated.go
index d5f1d5b8e1..56fa836f40 100644
--- a/internal/diagnostics/diagnostics_generated.go
+++ b/internal/diagnostics/diagnostics_generated.go
@@ -2276,7 +2276,7 @@ var Unknown_build_option_0 = &Message{code: 5072, category: CategoryError, key:
var Build_option_0_requires_a_value_of_type_1 = &Message{code: 5073, category: CategoryError, key: "Build_option_0_requires_a_value_of_type_1_5073", text: "Build option '{0}' requires a value of type {1}."}
-var Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified = &Message{code: 5074, category: CategoryError, key: "Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBui_5074", text: "Option '--incremental' can only be specified using tsconfig, emitting to single file or when option '--tsBuildInfoFile' is specified."}
+var Failed_to_update_timestamp_of_file_0 = &Message{code: 5074, category: CategoryMessage, key: "Failed_to_update_timestamp_of_file_0_5074", text: "Failed to update timestamp of file '{0}'."}
var X_0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2 = &Message{code: 5075, category: CategoryError, key: "_0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_5075", text: "'{0}' is assignable to the constraint of type '{1}', but '{1}' could be instantiated with a different subtype of constraint '{2}'."}
@@ -2858,7 +2858,7 @@ var Project_0_is_up_to_date_because_newest_input_1_is_older_than_output_2 = &Mes
var Project_0_is_out_of_date_because_output_file_1_does_not_exist = &Message{code: 6352, category: CategoryMessage, key: "Project_0_is_out_of_date_because_output_file_1_does_not_exist_6352", text: "Project '{0}' is out of date because output file '{1}' does not exist"}
-var Project_0_is_out_of_date_because_its_dependency_1_is_out_of_date = &Message{code: 6353, category: CategoryMessage, key: "Project_0_is_out_of_date_because_its_dependency_1_is_out_of_date_6353", text: "Project '{0}' is out of date because its dependency '{1}' is out of date"}
+var Failed_to_delete_file_0 = &Message{code: 6353, category: CategoryMessage, key: "Failed_to_delete_file_0_6353", text: "Failed to delete file '{0}'."}
var Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies = &Message{code: 6354, category: CategoryMessage, key: "Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies_6354", text: "Project '{0}' is up to date with .d.ts files from its dependencies"}
@@ -2938,7 +2938,7 @@ var Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_some_of_the
var Project_0_is_up_to_date_but_needs_to_update_timestamps_of_output_files_that_are_older_than_input_files = &Message{code: 6400, category: CategoryMessage, key: "Project_0_is_up_to_date_but_needs_to_update_timestamps_of_output_files_that_are_older_than_input_fil_6400", text: "Project '{0}' is up to date but needs to update timestamps of output files that are older than input files"}
-var Project_0_is_out_of_date_because_there_was_error_reading_file_1 = &Message{code: 6401, category: CategoryMessage, key: "Project_0_is_out_of_date_because_there_was_error_reading_file_1_6401", text: "Project '{0}' is out of date because there was error reading file '{1}'"}
+var Project_0_is_out_of_date_because_config_file_does_not_exist = &Message{code: 6401, category: CategoryMessage, key: "Project_0_is_out_of_date_because_config_file_does_not_exist_6401", text: "Project '{0}' is out of date because config file does not exist."}
var Resolving_in_0_mode_with_conditions_1 = &Message{code: 6402, category: CategoryMessage, key: "Resolving_in_0_mode_with_conditions_1_6402", text: "Resolving in {0} mode with conditions {1}."}
@@ -2976,7 +2976,7 @@ var Searching_all_ancestor_node_modules_directories_for_fallback_extensions_Colo
var Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_program_needs_to_report_errors = &Message{code: 6419, category: CategoryMessage, key: "Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_program_needs_to_report_errors_6419", text: "Project '{0}' is out of date because buildinfo file '{1}' indicates that program needs to report errors."}
-var Project_0_is_out_of_date_because_1 = &Message{code: 6420, category: CategoryMessage, key: "Project_0_is_out_of_date_because_1_6420", text: "Project '{0}' is out of date because {1}."}
+var Project_0_is_out_of_date_because_input_1_does_not_exist = &Message{code: 6420, category: CategoryMessage, key: "Project_0_is_out_of_date_because_input_1_does_not_exist_6420", text: "Project '{0}' is out of date because input '{1}' does not exist."}
var Rewrite_ts_tsx_mts_and_cts_file_extensions_in_relative_import_paths_to_their_JavaScript_equivalent_in_output_files = &Message{code: 6421, category: CategoryMessage, key: "Rewrite_ts_tsx_mts_and_cts_file_extensions_in_relative_import_paths_to_their_JavaScript_equivalent_i_6421", text: "Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files."}
diff --git a/internal/diagnostics/extraDiagnosticMessages.json b/internal/diagnostics/extraDiagnosticMessages.json
index 4e64552426..8b91e65d9f 100644
--- a/internal/diagnostics/extraDiagnosticMessages.json
+++ b/internal/diagnostics/extraDiagnosticMessages.json
@@ -22,5 +22,21 @@
"A JSDoc '@type' tag may not occur with a '@param' or '@returns' tag.": {
"category": "Error",
"code": 8040
+ },
+ "Failed to delete file '{0}'.": {
+ "category": "Message",
+ "code": 6353
+ },
+ "Project '{0}' is out of date because config file does not exist.": {
+ "category": "Message",
+ "code": 6401
+ },
+ "Project '{0}' is out of date because input '{1}' does not exist.": {
+ "category": "Message",
+ "code": 6420
+ },
+ "Failed to update timestamp of file '{0}'.": {
+ "category": "Message",
+ "code": 5074
}
}
diff --git a/internal/diagnosticwriter/diagnosticwriter.go b/internal/diagnosticwriter/diagnosticwriter.go
index 7001bed49e..520f769e8d4 100644
--- a/internal/diagnosticwriter/diagnosticwriter.go
+++ b/internal/diagnosticwriter/diagnosticwriter.go
@@ -39,7 +39,6 @@ func FormatDiagnosticsWithColorAndContext(output io.Writer, diags []*ast.Diagnos
if len(diags) == 0 {
return
}
-
for i, diagnostic := range diags {
if i > 0 {
fmt.Fprint(output, formatOpts.NewLine)
@@ -386,3 +385,15 @@ func WriteFormatDiagnostic(output io.Writer, diagnostic *ast.Diagnostic, formatO
WriteFlattenedDiagnosticMessage(output, diagnostic, formatOpts.NewLine)
fmt.Fprint(output, formatOpts.NewLine)
}
+
+func FormatDiagnosticsStatusWithColorAndTime(output io.Writer, time string, diag *ast.Diagnostic, formatOpts *FormattingOptions) {
+ fmt.Fprint(output, "[")
+ writeWithStyleAndReset(output, time, foregroundColorEscapeGrey)
+ fmt.Fprint(output, "] ")
+ WriteFlattenedDiagnosticMessage(output, diag, formatOpts.NewLine)
+}
+
+func FormatDiagnosticsStatusAndTime(output io.Writer, time string, diag *ast.Diagnostic, formatOpts *FormattingOptions) {
+ fmt.Fprint(output, time, " - ")
+ WriteFlattenedDiagnosticMessage(output, diag, formatOpts.NewLine)
+}
diff --git a/internal/execute/build/buildtask.go b/internal/execute/build/buildtask.go
new file mode 100644
index 0000000000..8c32163e30
--- /dev/null
+++ b/internal/execute/build/buildtask.go
@@ -0,0 +1,578 @@
+package build
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "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/diagnostics"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/tsc"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+type buildTask struct {
+ config string
+ resolved *tsoptions.ParsedCommandLine
+ upStream []*buildTask
+ status *upToDateStatus
+ done chan struct{}
+
+ // task reporting
+ builder strings.Builder
+ errors []*ast.Diagnostic
+ reportStatus tsc.DiagnosticReporter
+ diagnosticReporter tsc.DiagnosticReporter
+ exitStatus tsc.ExitStatus
+ statistics *tsc.Statistics
+ program *incremental.Program
+ pseudoBuild bool
+ filesToDelete []string
+ prevReporter *buildTask
+ reportDone chan struct{}
+}
+
+func (t *buildTask) waitOnUpstream() []*upToDateStatus {
+ upStreamStatus := make([]*upToDateStatus, len(t.upStream))
+ for i, upstream := range t.upStream {
+ <-upstream.done
+ upStreamStatus[i] = upstream.status
+ }
+ return upStreamStatus
+}
+
+func (t *buildTask) unblockDownstream(status *upToDateStatus) {
+ t.status = status
+ close(t.done)
+}
+
+func (t *buildTask) reportDiagnostic(err *ast.Diagnostic) {
+ t.errors = append(t.errors, err)
+ t.diagnosticReporter(err)
+}
+
+func (t *buildTask) report(orchestrator *Orchestrator, configPath tspath.Path, buildResult *orchestratorResult) {
+ if t.prevReporter != nil {
+ <-t.prevReporter.reportDone
+ }
+ if len(t.errors) > 0 {
+ buildResult.errors = append(core.IfElse(buildResult.errors != nil, buildResult.errors, []*ast.Diagnostic{}), t.errors...)
+ }
+ fmt.Fprint(orchestrator.opts.Sys.Writer(), t.builder.String())
+ if t.exitStatus > buildResult.result.Status {
+ buildResult.result.Status = t.exitStatus
+ }
+ if t.statistics != nil {
+ buildResult.programStats = append(buildResult.programStats, t.statistics)
+ }
+ if t.program != nil {
+ buildResult.result.IncrementalProgram = append(buildResult.result.IncrementalProgram, t.program)
+ buildResult.statistics.ProjectsBuilt++
+ }
+ if t.pseudoBuild {
+ buildResult.statistics.TimestampUpdates++
+ }
+ buildResult.filesToDelete = append(buildResult.filesToDelete, t.filesToDelete...)
+ close(t.reportDone)
+}
+
+func (t *buildTask) buildProject(orchestrator *Orchestrator, path tspath.Path) {
+ // Wait on upstream tasks to complete
+ upStreamStatus := t.waitOnUpstream()
+ status := t.getUpToDateStatus(orchestrator, path, upStreamStatus)
+ t.reportUpToDateStatus(orchestrator, status)
+ if handled := t.handleStatusThatDoesntRequireBuild(orchestrator, status); handled == nil {
+ if orchestrator.opts.Command.BuildOptions.Verbose.IsTrue() {
+ t.reportStatus(ast.NewCompilerDiagnostic(diagnostics.Building_project_0, orchestrator.relativeFileName(t.config)))
+ }
+
+ // Real build
+ var compileTimes tsc.CompileTimes
+ configAndTime, _ := orchestrator.host.resolvedReferences.Load(path)
+ compileTimes.ConfigTime = configAndTime.time
+ buildInfoReadStart := orchestrator.opts.Sys.Now()
+ oldProgram := incremental.ReadBuildInfoProgram(t.resolved, orchestrator.host, orchestrator.host)
+ compileTimes.BuildInfoReadTime = orchestrator.opts.Sys.Now().Sub(buildInfoReadStart)
+ parseStart := orchestrator.opts.Sys.Now()
+ program := compiler.NewProgram(compiler.ProgramOptions{
+ Config: t.resolved,
+ Host: &compilerHost{
+ host: orchestrator.host,
+ trace: tsc.GetTraceWithWriterFromSys(&t.builder, orchestrator.opts.Testing),
+ },
+ JSDocParsingMode: ast.JSDocParsingModeParseForTypeErrors,
+ })
+ compileTimes.ParseTime = orchestrator.opts.Sys.Now().Sub(parseStart)
+ changesComputeStart := orchestrator.opts.Sys.Now()
+ t.program = incremental.NewProgram(program, oldProgram, orchestrator.host, orchestrator.opts.Testing != nil)
+ compileTimes.ChangesComputeTime = orchestrator.opts.Sys.Now().Sub(changesComputeStart)
+
+ result, statistics := tsc.EmitAndReportStatistics(
+ orchestrator.opts.Sys,
+ t.program,
+ program,
+ t.resolved,
+ t.reportDiagnostic,
+ tsc.QuietDiagnosticsReporter,
+ &t.builder,
+ compileTimes,
+ orchestrator.opts.Testing,
+ )
+ t.exitStatus = result.Status
+ t.statistics = statistics
+ if (!program.Options().NoEmitOnError.IsTrue() || len(result.Diagnostics) == 0) &&
+ (len(result.EmitResult.EmittedFiles) > 0 || status.kind != upToDateStatusTypeOutOfDateBuildInfoWithErrors) {
+ // Update time stamps for rest of the outputs
+ t.updateTimeStamps(orchestrator, result.EmitResult.EmittedFiles, diagnostics.Updating_unchanged_output_timestamps_of_project_0)
+ }
+
+ if result.Status == tsc.ExitStatusDiagnosticsPresent_OutputsSkipped || result.Status == tsc.ExitStatusDiagnosticsPresent_OutputsGenerated {
+ status = &upToDateStatus{kind: upToDateStatusTypeBuildErrors}
+ } else {
+ status = &upToDateStatus{kind: upToDateStatusTypeUpToDate}
+ }
+ } else {
+ status = handled
+ if t.resolved != nil {
+ for _, diagnostic := range t.resolved.GetConfigFileParsingDiagnostics() {
+ t.reportDiagnostic(diagnostic)
+ }
+ }
+ if len(t.errors) > 0 {
+ t.exitStatus = tsc.ExitStatusDiagnosticsPresent_OutputsSkipped
+ }
+ }
+ t.unblockDownstream(status)
+}
+
+func (t *buildTask) handleStatusThatDoesntRequireBuild(orchestrator *Orchestrator, status *upToDateStatus) *upToDateStatus {
+ switch status.kind {
+ case upToDateStatusTypeUpToDate:
+ if orchestrator.opts.Command.BuildOptions.Dry.IsTrue() {
+ t.reportStatus(ast.NewCompilerDiagnostic(diagnostics.Project_0_is_up_to_date, t.config))
+ }
+ return status
+ case upToDateStatusTypeUpstreamErrors:
+ upstreamStatus := status.data.(*upstreamErrors)
+ if orchestrator.opts.Command.BuildOptions.Verbose.IsTrue() {
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ core.IfElse(
+ upstreamStatus.refHasUpstreamErrors,
+ diagnostics.Skipping_build_of_project_0_because_its_dependency_1_was_not_built,
+ diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors,
+ ),
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(upstreamStatus.ref),
+ ))
+ }
+ return status
+ case upToDateStatusTypeSolution:
+ return status
+ case upToDateStatusTypeConfigFileNotFound:
+ t.reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.File_0_not_found, t.config))
+ return status
+ }
+
+ // update timestamps
+ if status.isPseudoBuild() {
+ if orchestrator.opts.Command.BuildOptions.Dry.IsTrue() {
+ t.reportStatus(ast.NewCompilerDiagnostic(diagnostics.A_non_dry_build_would_update_timestamps_for_output_of_project_0, t.config))
+ status = &upToDateStatus{kind: upToDateStatusTypeUpToDate}
+ return status
+ }
+
+ t.updateTimeStamps(orchestrator, nil, diagnostics.Updating_output_timestamps_of_project_0)
+ status = &upToDateStatus{kind: upToDateStatusTypeUpToDate}
+ t.pseudoBuild = true
+ return status
+ }
+
+ if orchestrator.opts.Command.BuildOptions.Dry.IsTrue() {
+ t.reportStatus(ast.NewCompilerDiagnostic(diagnostics.A_non_dry_build_would_build_project_0, t.config))
+ status = &upToDateStatus{kind: upToDateStatusTypeUpToDate}
+ return status
+ }
+ return nil
+}
+
+func (t *buildTask) getUpToDateStatus(orchestrator *Orchestrator, configPath tspath.Path, upStreamStatus []*upToDateStatus) *upToDateStatus {
+ // Config file not found
+ if t.resolved == nil {
+ return &upToDateStatus{kind: upToDateStatusTypeConfigFileNotFound}
+ }
+
+ // Solution - nothing to build
+ if len(t.resolved.FileNames()) == 0 && t.resolved.ProjectReferences() != nil {
+ return &upToDateStatus{kind: upToDateStatusTypeSolution}
+ }
+
+ for index, upstreamStatus := range upStreamStatus {
+ if upstreamStatus == nil {
+ // Not dependent on this upstream project (expected cycle was detected and hence skipped)
+ continue
+ }
+
+ if orchestrator.opts.Command.BuildOptions.StopBuildOnErrors.IsTrue() && upstreamStatus.isError() {
+ // Upstream project has errors, so we cannot build this project
+ return &upToDateStatus{kind: upToDateStatusTypeUpstreamErrors, data: &upstreamErrors{t.resolved.ProjectReferences()[index].Path, upstreamStatus.kind == upToDateStatusTypeUpstreamErrors}}
+ }
+ }
+
+ if orchestrator.opts.Command.BuildOptions.Force.IsTrue() {
+ return &upToDateStatus{kind: upToDateStatusTypeForceBuild}
+ }
+
+ // Check the build info
+ buildInfoPath := t.resolved.GetBuildInfoFileName()
+ buildInfo := orchestrator.host.readOrStoreBuildInfo(configPath, buildInfoPath)
+ if buildInfo == nil {
+ return &upToDateStatus{kind: upToDateStatusTypeOutputMissing, data: buildInfoPath}
+ }
+
+ // build info version
+ if !buildInfo.IsValidVersion() {
+ return &upToDateStatus{kind: upToDateStatusTypeTsVersionOutputOfDate, data: buildInfo.Version}
+ }
+
+ // Report errors if build info indicates errors
+ if buildInfo.Errors || // Errors that need to be reported irrespective of "--noCheck"
+ (!t.resolved.CompilerOptions().NoCheck.IsTrue() && (buildInfo.SemanticErrors || buildInfo.CheckPending)) { // Errors without --noCheck
+ return &upToDateStatus{kind: upToDateStatusTypeOutOfDateBuildInfoWithErrors, data: buildInfoPath}
+ }
+
+ if t.resolved.CompilerOptions().IsIncremental() {
+ if !buildInfo.IsIncremental() {
+ // Program options out of date
+ return &upToDateStatus{kind: upToDateStatusTypeOutOfDateOptions, data: buildInfoPath}
+ }
+
+ // Errors need to be reported if build info has errors
+ if (t.resolved.CompilerOptions().GetEmitDeclarations() && buildInfo.EmitDiagnosticsPerFile != nil) || // Always reported errors
+ (!t.resolved.CompilerOptions().NoCheck.IsTrue() && // Semantic errors if not --noCheck
+ (buildInfo.ChangeFileSet != nil || buildInfo.SemanticDiagnosticsPerFile != nil)) {
+ return &upToDateStatus{kind: upToDateStatusTypeOutOfDateBuildInfoWithErrors, data: buildInfoPath}
+ }
+
+ // Pending emit files
+ if !t.resolved.CompilerOptions().NoEmit.IsTrue() &&
+ (buildInfo.ChangeFileSet != nil || buildInfo.AffectedFilesPendingEmit != nil) {
+ return &upToDateStatus{kind: upToDateStatusTypeOutOfDateBuildInfoWithPendingEmit, data: buildInfoPath}
+ }
+
+ // Some of the emit files like source map or dts etc are not yet done
+ if buildInfo.IsEmitPending(t.resolved, tspath.GetDirectoryPath(tspath.GetNormalizedAbsolutePath(buildInfoPath, orchestrator.comparePathsOptions.CurrentDirectory))) {
+ return &upToDateStatus{kind: upToDateStatusTypeOutOfDateOptions, data: buildInfoPath}
+ }
+ }
+ var inputTextUnchanged bool
+ oldestOutputFileAndTime := fileAndTime{buildInfoPath, orchestrator.host.GetMTime(buildInfoPath)}
+ var newestInputFileAndTime fileAndTime
+ var seenRoots collections.Set[tspath.Path]
+ var buildInfoRootInfoReader *incremental.BuildInfoRootInfoReader
+ for _, inputFile := range t.resolved.FileNames() {
+ inputTime := orchestrator.host.GetMTime(inputFile)
+ if inputTime.IsZero() {
+ return &upToDateStatus{kind: upToDateStatusTypeInputFileMissing, data: inputFile}
+ }
+ inputPath := orchestrator.toPath(inputFile)
+ if inputTime.After(oldestOutputFileAndTime.time) {
+ var version string
+ var currentVersion string
+ if buildInfo.IsIncremental() {
+ if buildInfoRootInfoReader == nil {
+ buildInfoRootInfoReader = buildInfo.GetBuildInfoRootInfoReader(tspath.GetDirectoryPath(tspath.GetNormalizedAbsolutePath(buildInfoPath, orchestrator.comparePathsOptions.CurrentDirectory)), orchestrator.comparePathsOptions)
+ }
+ buildInfoFileInfo, resolvedInputPath := buildInfoRootInfoReader.GetBuildInfoFileInfo(inputPath)
+ if fileInfo := buildInfoFileInfo.GetFileInfo(); fileInfo != nil && fileInfo.Version() != "" {
+ version = fileInfo.Version()
+ if text, ok := orchestrator.host.FS().ReadFile(string(resolvedInputPath)); ok {
+ currentVersion = incremental.ComputeHash(text, orchestrator.opts.Testing != nil)
+ if version == currentVersion {
+ inputTextUnchanged = true
+ }
+ }
+ }
+ }
+
+ if version == "" || version != currentVersion {
+ return &upToDateStatus{kind: upToDateStatusTypeInputFileNewer, data: &inputOutputName{inputFile, buildInfoPath}}
+ }
+ }
+ if inputTime.After(newestInputFileAndTime.time) {
+ newestInputFileAndTime = fileAndTime{inputFile, inputTime}
+ }
+ seenRoots.Add(inputPath)
+ }
+
+ if buildInfoRootInfoReader == nil {
+ buildInfoRootInfoReader = buildInfo.GetBuildInfoRootInfoReader(tspath.GetDirectoryPath(tspath.GetNormalizedAbsolutePath(buildInfoPath, orchestrator.comparePathsOptions.CurrentDirectory)), orchestrator.comparePathsOptions)
+ }
+ for root := range buildInfoRootInfoReader.Roots() {
+ if !seenRoots.Has(root) {
+ // File was root file when project was built but its not any more
+ return &upToDateStatus{kind: upToDateStatusTypeOutOfDateRoots, data: &inputOutputName{string(root), buildInfoPath}}
+ }
+ }
+
+ if !t.resolved.CompilerOptions().IsIncremental() {
+ // Check output file stamps
+ for outputFile := range t.resolved.GetOutputFileNames() {
+ outputTime := orchestrator.host.GetMTime(outputFile)
+ if outputTime.IsZero() {
+ // Output file missing
+ return &upToDateStatus{kind: upToDateStatusTypeOutputMissing, data: outputFile}
+ }
+
+ if outputTime.Before(newestInputFileAndTime.time) {
+ // Output file is older than input file
+ return &upToDateStatus{kind: upToDateStatusTypeInputFileNewer, data: &inputOutputName{newestInputFileAndTime.file, outputFile}}
+ }
+
+ if outputTime.Before(oldestOutputFileAndTime.time) {
+ oldestOutputFileAndTime = fileAndTime{outputFile, outputTime}
+ }
+ }
+ }
+
+ var refDtsUnchanged bool
+ for index, upstreamStatus := range upStreamStatus {
+ if upstreamStatus == nil || upstreamStatus.kind == upToDateStatusTypeSolution {
+ // Not dependent on the status or this upstream project
+ // (eg: expected cycle was detected and hence skipped, or is solution)
+ continue
+ }
+
+ // If the upstream project's newest file is older than our oldest output,
+ // we can't be out of date because of it
+ // inputTime will not be present if we just built this project or updated timestamps
+ // - in that case we do want to either build or update timestamps
+ refInputOutputFileAndTime := upstreamStatus.inputOutputFileAndTime()
+ if refInputOutputFileAndTime != nil && !refInputOutputFileAndTime.input.time.IsZero() && refInputOutputFileAndTime.input.time.Before(oldestOutputFileAndTime.time) {
+ continue
+ }
+
+ // Check if tsbuildinfo path is shared, then we need to rebuild
+ if orchestrator.host.hasConflictingBuildInfo(configPath) {
+ return &upToDateStatus{kind: upToDateStatusTypeInputFileNewer, data: &inputOutputName{t.resolved.ProjectReferences()[index].Path, oldestOutputFileAndTime.file}}
+ }
+
+ // If the upstream project has only change .d.ts files, and we've built
+ // *after* those files, then we're "pseudo up to date" and eligible for a fast rebuild
+ newestDtsChangeTime := orchestrator.host.getLatestChangedDtsMTime(t.resolved.ResolvedProjectReferencePaths()[index])
+ if !newestDtsChangeTime.IsZero() && newestDtsChangeTime.Before(oldestOutputFileAndTime.time) {
+ refDtsUnchanged = true
+ continue
+ }
+
+ // We have an output older than an upstream output - we are out of date
+ return &upToDateStatus{kind: upToDateStatusTypeInputFileNewer, data: &inputOutputName{t.resolved.ProjectReferences()[index].Path, oldestOutputFileAndTime.file}}
+ }
+
+ checkInputFileTime := func(inputFile string) *upToDateStatus {
+ inputTime := orchestrator.host.GetMTime(inputFile)
+ if inputTime.After(oldestOutputFileAndTime.time) {
+ // Output file is older than input file
+ return &upToDateStatus{kind: upToDateStatusTypeInputFileNewer, data: &inputOutputName{inputFile, oldestOutputFileAndTime.file}}
+ }
+ return nil
+ }
+
+ configStatus := checkInputFileTime(t.config)
+ if configStatus != nil {
+ return configStatus
+ }
+
+ for _, extendedConfig := range t.resolved.ExtendedSourceFiles() {
+ extendedConfigStatus := checkInputFileTime(extendedConfig)
+ if extendedConfigStatus != nil {
+ return extendedConfigStatus
+ }
+ }
+
+ // !!! sheetal TODO : watch??
+ // // Check package file time
+ // const packageJsonLookups = state.lastCachedPackageJsonLookups.get(resolvedPath);
+ // const dependentPackageFileStatus = packageJsonLookups && forEachKey(
+ // packageJsonLookups,
+ // path => checkConfigFileUpToDateStatus(state, path, oldestOutputFileTime, oldestOutputFileName),
+ // );
+ // if (dependentPackageFileStatus) return dependentPackageFileStatus;
+
+ return &upToDateStatus{
+ kind: core.IfElse(
+ refDtsUnchanged,
+ upToDateStatusTypeUpToDateWithUpstreamTypes,
+ core.IfElse(inputTextUnchanged, upToDateStatusTypeUpToDateWithInputFileText, upToDateStatusTypeUpToDate),
+ ),
+ data: &inputOutputFileAndTime{newestInputFileAndTime, oldestOutputFileAndTime, buildInfoPath},
+ }
+}
+
+func (t *buildTask) reportUpToDateStatus(orchestrator *Orchestrator, status *upToDateStatus) {
+ if !orchestrator.opts.Command.BuildOptions.Verbose.IsTrue() {
+ return
+ }
+ switch status.kind {
+ case upToDateStatusTypeConfigFileNotFound:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_config_file_does_not_exist,
+ orchestrator.relativeFileName(t.config),
+ ))
+ case upToDateStatusTypeUpstreamErrors:
+ upstreamStatus := status.data.(*upstreamErrors)
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ core.IfElse(
+ upstreamStatus.refHasUpstreamErrors,
+ diagnostics.Project_0_can_t_be_built_because_its_dependency_1_was_not_built,
+ diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors,
+ ),
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(upstreamStatus.ref),
+ ))
+ case upToDateStatusTypeUpToDate:
+ inputOutputFileAndTime := status.data.(*inputOutputFileAndTime)
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_output_2,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(inputOutputFileAndTime.input.file),
+ orchestrator.relativeFileName(inputOutputFileAndTime.output.file),
+ ))
+ case upToDateStatusTypeUpToDateWithUpstreamTypes:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies,
+ orchestrator.relativeFileName(t.config),
+ ))
+ case upToDateStatusTypeUpToDateWithInputFileText:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_up_to_date_but_needs_to_update_timestamps_of_output_files_that_are_older_than_input_files,
+ orchestrator.relativeFileName(t.config),
+ ))
+ case upToDateStatusTypeInputFileMissing:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_input_1_does_not_exist,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(status.data.(string)),
+ ))
+ case upToDateStatusTypeOutputMissing:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(status.data.(string)),
+ ))
+ case upToDateStatusTypeInputFileNewer:
+ inputOutput := status.data.(*inputOutputName)
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_output_1_is_older_than_input_2,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(inputOutput.output),
+ orchestrator.relativeFileName(inputOutput.input),
+ ))
+ case upToDateStatusTypeOutOfDateBuildInfoWithPendingEmit:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_some_of_the_changes_were_not_emitted,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(status.data.(string)),
+ ))
+ case upToDateStatusTypeOutOfDateBuildInfoWithErrors:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_program_needs_to_report_errors,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(status.data.(string)),
+ ))
+ case upToDateStatusTypeOutOfDateOptions:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_there_is_change_in_compilerOptions,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(status.data.(string)),
+ ))
+ case upToDateStatusTypeOutOfDateRoots:
+ inputOutput := status.data.(*inputOutputName)
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_file_2_was_root_file_of_compilation_but_not_any_more,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(inputOutput.output),
+ orchestrator.relativeFileName(inputOutput.input),
+ ))
+ case upToDateStatusTypeTsVersionOutputOfDate:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2,
+ orchestrator.relativeFileName(t.config),
+ orchestrator.relativeFileName(status.data.(string)),
+ core.Version(),
+ ))
+ case upToDateStatusTypeForceBuild:
+ t.reportStatus(ast.NewCompilerDiagnostic(
+ diagnostics.Project_0_is_being_forcibly_rebuilt,
+ orchestrator.relativeFileName(t.config),
+ ))
+ case upToDateStatusTypeSolution:
+ // Does not need to report status
+ default:
+ panic(fmt.Sprintf("Unknown up to date status kind: %v", status.kind))
+ }
+}
+
+func (t *buildTask) updateTimeStamps(orchestrator *Orchestrator, emittedFiles []string, verboseMessage *diagnostics.Message) {
+ if t.resolved.CompilerOptions().NoEmit.IsTrue() {
+ return
+ }
+ emitted := collections.NewSetFromItems(emittedFiles...)
+ var verboseMessageReported bool
+ updateTimeStamp := func(file string) {
+ if emitted.Has(file) {
+ return
+ }
+ if !verboseMessageReported && orchestrator.opts.Command.BuildOptions.Verbose.IsTrue() {
+ t.reportStatus(ast.NewCompilerDiagnostic(verboseMessage, orchestrator.relativeFileName(t.config)))
+ verboseMessageReported = true
+ }
+ err := orchestrator.host.SetMTime(file, orchestrator.opts.Sys.Now())
+ if err != nil {
+ t.reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Failed_to_update_timestamp_of_file_0, file))
+ }
+ }
+
+ if t.resolved.CompilerOptions().IsIncremental() {
+ updateTimeStamp(t.resolved.GetBuildInfoFileName())
+ } else {
+ for outputFile := range t.resolved.GetOutputFileNames() {
+ updateTimeStamp(outputFile)
+ }
+ }
+}
+
+func (t *buildTask) cleanProject(orchestrator *Orchestrator, path tspath.Path) {
+ if t.resolved == nil {
+ t.reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.File_0_not_found, t.config))
+ t.exitStatus = tsc.ExitStatusDiagnosticsPresent_OutputsSkipped
+ return
+ }
+
+ inputs := collections.NewSetFromItems(core.Map(t.resolved.FileNames(), orchestrator.toPath)...)
+ for outputFile := range t.resolved.GetOutputFileNames() {
+ t.cleanProjectOutput(orchestrator, outputFile, inputs)
+ }
+ t.cleanProjectOutput(orchestrator, t.resolved.GetBuildInfoFileName(), inputs)
+}
+
+func (t *buildTask) cleanProjectOutput(orchestrator *Orchestrator, outputFile string, inputs *collections.Set[tspath.Path]) {
+ outputPath := orchestrator.toPath(outputFile)
+ // If output name is same as input file name, do not delete and ignore the error
+ if inputs.Has(outputPath) {
+ return
+ }
+ if orchestrator.host.FS().FileExists(outputFile) {
+ if !orchestrator.opts.Command.BuildOptions.Dry.IsTrue() {
+ err := orchestrator.host.FS().Remove(outputFile)
+ if err != nil {
+ t.reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Failed_to_delete_file_0, outputFile))
+ }
+ } else {
+ t.filesToDelete = append(t.filesToDelete, outputFile)
+ }
+ }
+}
diff --git a/internal/execute/build/compilerHost.go b/internal/execute/build/compilerHost.go
new file mode 100644
index 0000000000..f11f06b9fc
--- /dev/null
+++ b/internal/execute/build/compilerHost.go
@@ -0,0 +1,40 @@
+package build
+
+import (
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/compiler"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+ "github.com/microsoft/typescript-go/internal/vfs"
+)
+
+type compilerHost struct {
+ host *host
+ trace func(msg string)
+}
+
+var _ compiler.CompilerHost = (*compilerHost)(nil)
+
+func (h *compilerHost) FS() vfs.FS {
+ return h.host.FS()
+}
+
+func (h *compilerHost) DefaultLibraryPath() string {
+ return h.host.DefaultLibraryPath()
+}
+
+func (h *compilerHost) GetCurrentDirectory() string {
+ return h.host.GetCurrentDirectory()
+}
+
+func (h *compilerHost) Trace(msg string) {
+ h.trace(msg)
+}
+
+func (h *compilerHost) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile {
+ return h.host.GetSourceFile(opts)
+}
+
+func (h *compilerHost) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine {
+ return h.host.GetResolvedProjectReference(fileName, path)
+}
diff --git a/internal/execute/build/graph_test.go b/internal/execute/build/graph_test.go
new file mode 100644
index 0000000000..0265b99d36
--- /dev/null
+++ b/internal/execute/build/graph_test.go
@@ -0,0 +1,120 @@
+package build_test
+
+import (
+ "fmt"
+ "slices"
+ "strings"
+ "testing"
+
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/execute/build"
+ "github.com/microsoft/typescript-go/internal/execute/tsctests"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "gotest.tools/v3/assert"
+)
+
+func TestBuildOrderGenerator(t *testing.T) {
+ t.Parallel()
+ testCases := []*buildOrderTestCase{
+ {"specify two roots", []string{"A", "G"}, []string{"D", "E", "C", "B", "A", "G"}, false},
+ {"multiple parts of the same graph in various orders", []string{"A"}, []string{"D", "E", "C", "B", "A"}, false},
+ {"multiple parts of the same graph in various orders", []string{"A", "C", "D"}, []string{"D", "E", "C", "B", "A"}, false},
+ {"multiple parts of the same graph in various orders", []string{"D", "C", "A"}, []string{"D", "E", "C", "B", "A"}, false},
+ {"other orderings", []string{"F"}, []string{"E", "F"}, false},
+ {"other orderings", []string{"E"}, []string{"E"}, false},
+ {"other orderings", []string{"F", "C", "A"}, []string{"E", "F", "D", "C", "B", "A"}, false},
+ {"returns circular order", []string{"H"}, []string{"E", "J", "I", "H"}, true},
+ {"returns circular order", []string{"A", "H"}, []string{"D", "E", "C", "B", "A", "J", "I", "H"}, true},
+ }
+ for _, testcase := range testCases {
+ testcase.run(t)
+ }
+}
+
+type buildOrderTestCase struct {
+ name string
+ projects []string
+ expected []string
+ circular bool
+}
+
+func (b *buildOrderTestCase) configName(project string) string {
+ return fmt.Sprintf("/home/src/workspaces/project/%s/tsconfig.json", project)
+}
+
+func (b *buildOrderTestCase) projectName(config string) string {
+ str := strings.TrimPrefix(config, "/home/src/workspaces/project/")
+ str = strings.TrimSuffix(str, "/tsconfig.json")
+ return str
+}
+
+func (b *buildOrderTestCase) run(t *testing.T) {
+ t.Helper()
+ t.Run(b.name+" - "+strings.Join(b.projects, ","), func(t *testing.T) {
+ t.Parallel()
+ files := make(map[string]any)
+ deps := map[string][]string{
+ "A": {"B", "C"},
+ "B": {"C", "D"},
+ "C": {"D", "E"},
+ "F": {"E"},
+ "H": {"I"},
+ "I": {"J"},
+ "J": {"H", "E"},
+ }
+ for _, project := range []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"} {
+ files[fmt.Sprintf("/home/src/workspaces/project/%s/%s.ts", project, project)] = "export {}"
+ referencesStr := ""
+ if deps, ok := deps[project]; ok {
+ referencesStr = fmt.Sprintf(`, "references": [%s]`, strings.Join(core.Map(deps, func(dep string) string {
+ return fmt.Sprintf(`{ "path": "../%s" }`, dep)
+ }), ","))
+ }
+ files[b.configName(project)] = fmt.Sprintf(`{
+ "compilerOptions": { "composite": true },
+ "files": ["./%s.ts"],
+ %s
+ }`, project, referencesStr)
+ }
+
+ sys := tsctests.NewTscSystem(files, true, "/home/src/workspaces/project")
+ args := append([]string{"--build", "--dry"}, b.projects...)
+ buildCommand := tsoptions.ParseBuildCommandLine(args, sys)
+ orchestrator := build.NewOrchestrator(build.Options{
+ Sys: sys,
+ Command: buildCommand,
+ })
+ orchestrator.GenerateGraph()
+ buildOrder := core.Map(orchestrator.Order(), b.projectName)
+ assert.DeepEqual(t, buildOrder, b.expected)
+
+ for index, project := range buildOrder {
+ upstream := core.Map(orchestrator.Upstream(b.configName(project)), b.projectName)
+ expectedUpstream := deps[project]
+ assert.Assert(t, len(upstream) <= len(expectedUpstream), fmt.Sprintf("Expected upstream for %s to be at most %d, got %d", project, len(expectedUpstream), len(upstream)))
+ for _, expected := range expectedUpstream {
+ if slices.Contains(buildOrder[:index], expected) {
+ assert.Assert(t, slices.Contains(upstream, expected), fmt.Sprintf("Expected upstream for %s to contain %s", project, expected))
+ } else {
+ assert.Assert(t, !slices.Contains(upstream, expected), fmt.Sprintf("Expected upstream for %s to not contain %s", project, expected))
+ }
+ }
+ }
+
+ if !b.circular {
+ for project, projectDeps := range deps {
+ child := b.configName(project)
+ childIndex := slices.Index(buildOrder, child)
+ if childIndex == -1 {
+ continue
+ }
+ for _, dep := range projectDeps {
+ parent := b.configName(dep)
+ parentIndex := slices.Index(buildOrder, parent)
+
+ assert.Assert(t, childIndex > parentIndex, fmt.Sprintf("Expecting child %s to be built after parent %s", project, dep))
+ }
+ }
+ }
+ })
+}
diff --git a/internal/execute/build/host.go b/internal/execute/build/host.go
new file mode 100644
index 0000000000..3f2a00c513
--- /dev/null
+++ b/internal/execute/build/host.go
@@ -0,0 +1,202 @@
+package build
+
+import (
+ "time"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/collections"
+ "github.com/microsoft/typescript-go/internal/compiler"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+ "github.com/microsoft/typescript-go/internal/vfs"
+)
+
+type configAndTime struct {
+ resolved *tsoptions.ParsedCommandLine
+ time time.Duration
+}
+
+type buildInfoAndConfig struct {
+ buildInfo *incremental.BuildInfo
+ config tspath.Path
+}
+
+type host struct {
+ builder *Orchestrator
+ host compiler.CompilerHost
+ extendedConfigCache collections.SyncMap[tspath.Path, *tsoptions.ExtendedConfigCacheEntry]
+ sourceFiles collections.SyncMap[ast.SourceFileParseOptions, *ast.SourceFile]
+ resolvedReferences collections.SyncMap[tspath.Path, *configAndTime]
+
+ buildInfos collections.SyncMap[tspath.Path, *buildInfoAndConfig]
+ mTimes collections.SyncMap[tspath.Path, time.Time]
+ latestChangedDtsFiles collections.SyncMap[tspath.Path, time.Time]
+}
+
+var (
+ _ vfs.FS = (*host)(nil)
+ _ compiler.CompilerHost = (*host)(nil)
+ _ incremental.BuildInfoReader = (*host)(nil)
+ _ incremental.BuildHost = (*host)(nil)
+)
+
+func (h *host) FS() vfs.FS {
+ return h
+}
+
+func (h *host) UseCaseSensitiveFileNames() bool {
+ return h.host.FS().UseCaseSensitiveFileNames()
+}
+
+func (h *host) FileExists(path string) bool {
+ return h.host.FS().FileExists(path)
+}
+
+func (h *host) ReadFile(path string) (string, bool) {
+ return h.host.FS().ReadFile(path)
+}
+
+func (h *host) WriteFile(path string, data string, writeByteOrderMark bool) error {
+ err := h.host.FS().WriteFile(path, data, writeByteOrderMark)
+ if err == nil {
+ filePath := h.builder.toPath(path)
+ h.buildInfos.Delete(filePath)
+ h.mTimes.Delete(filePath)
+ }
+ return err
+}
+
+func (h *host) Remove(path string) error {
+ return h.host.FS().Remove(path)
+}
+
+func (h *host) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ return h.host.FS().Chtimes(path, aTime, mTime)
+}
+
+func (h *host) DirectoryExists(path string) bool {
+ return h.host.FS().DirectoryExists(path)
+}
+
+func (h *host) GetAccessibleEntries(path string) vfs.Entries {
+ return h.host.FS().GetAccessibleEntries(path)
+}
+
+func (h *host) Stat(path string) vfs.FileInfo {
+ return h.host.FS().Stat(path)
+}
+
+func (h *host) WalkDir(root string, walkFn vfs.WalkDirFunc) error {
+ return h.host.FS().WalkDir(root, walkFn)
+}
+
+func (h *host) Realpath(path string) string {
+ return h.host.FS().Realpath(path)
+}
+
+func (h *host) DefaultLibraryPath() string {
+ return h.host.DefaultLibraryPath()
+}
+
+func (h *host) GetCurrentDirectory() string {
+ return h.host.GetCurrentDirectory()
+}
+
+func (h *host) Trace(msg string) {
+ panic("build.Orchestrator.host does not support tracing, use a different host for tracing")
+}
+
+func (h *host) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile {
+ if existing, loaded := h.sourceFiles.Load(opts); loaded {
+ return existing
+ }
+
+ file := h.host.GetSourceFile(opts)
+ file, _ = h.sourceFiles.LoadOrStore(opts, file)
+ return file
+}
+
+func (h *host) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine {
+ if existing, loaded := h.resolvedReferences.Load(path); loaded {
+ return existing.resolved
+ }
+ configStart := h.builder.opts.Sys.Now()
+ commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, h.builder.opts.Command.CompilerOptions, h, &h.extendedConfigCache)
+ configTime := h.builder.opts.Sys.Now().Sub(configStart)
+ configAndTime, _ := h.resolvedReferences.LoadOrStore(path, &configAndTime{resolved: commandLine, time: configTime})
+ return configAndTime.resolved
+}
+
+func (h *host) ReadBuildInfo(buildInfoFileName string) *incremental.BuildInfo {
+ path := h.builder.toPath(buildInfoFileName)
+ if existing, loaded := h.buildInfos.Load(path); loaded {
+ return existing.buildInfo
+ }
+ return nil
+}
+
+func (h *host) readOrStoreBuildInfo(configPath tspath.Path, buildInfoFileName string) *incremental.BuildInfo {
+ if existing, loaded := h.buildInfos.Load(h.builder.toPath(buildInfoFileName)); loaded {
+ return existing.buildInfo
+ }
+
+ buildInfo := incremental.NewBuildInfoReader(h).ReadBuildInfo(buildInfoFileName)
+ entry := &buildInfoAndConfig{buildInfo, configPath}
+ entry, _ = h.buildInfos.LoadOrStore(h.builder.toPath(buildInfoFileName), entry)
+ return entry.buildInfo
+}
+
+func (h *host) hasConflictingBuildInfo(configPath tspath.Path) bool {
+ if existing, loaded := h.buildInfos.Load(configPath); loaded {
+ return existing.config != configPath
+ }
+ return false
+}
+
+func (h *host) GetMTime(file string) time.Time {
+ path := h.builder.toPath(file)
+ if existing, loaded := h.mTimes.Load(path); loaded {
+ return existing
+ }
+ stat := h.host.FS().Stat(file)
+ var mTime time.Time
+ if stat != nil {
+ mTime = stat.ModTime()
+ }
+ mTime, _ = h.mTimes.LoadOrStore(path, mTime)
+ return mTime
+}
+
+func (h *host) SetMTime(file string, mTime time.Time) error {
+ path := h.builder.toPath(file)
+ err := h.host.FS().Chtimes(file, time.Time{}, mTime)
+ if err == nil {
+ h.mTimes.Store(path, mTime)
+ }
+ return err
+}
+
+func (h *host) getLatestChangedDtsMTime(config string) time.Time {
+ path := h.builder.toPath(config)
+ if existing, loaded := h.latestChangedDtsFiles.Load(path); loaded {
+ return existing
+ }
+
+ var changedDtsMTime time.Time
+ if configAndTime, loaded := h.resolvedReferences.Load(path); loaded {
+ buildInfoPath := configAndTime.resolved.GetBuildInfoFileName()
+ buildInfo := h.readOrStoreBuildInfo(path, buildInfoPath)
+ if buildInfo != nil && buildInfo.LatestChangedDtsFile != "" {
+ changedDtsMTime = h.GetMTime(
+ tspath.GetNormalizedAbsolutePath(
+ buildInfo.LatestChangedDtsFile,
+ tspath.GetDirectoryPath(tspath.GetNormalizedAbsolutePath(buildInfoPath, h.GetCurrentDirectory())),
+ ),
+ )
+ }
+ }
+
+ changedDtsMTime, _ = h.mTimes.LoadOrStore(path, changedDtsMTime)
+ return changedDtsMTime
+}
diff --git a/internal/execute/build/orchestrator.go b/internal/execute/build/orchestrator.go
new file mode 100644
index 0000000000..27535deb86
--- /dev/null
+++ b/internal/execute/build/orchestrator.go
@@ -0,0 +1,236 @@
+package build
+
+import (
+ "io"
+ "strings"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "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/diagnostics"
+ "github.com/microsoft/typescript-go/internal/execute/tsc"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+type Options struct {
+ Sys tsc.System
+ Command *tsoptions.ParsedBuildCommandLine
+ Testing tsc.CommandLineTesting
+}
+
+type orchestratorResult struct {
+ result tsc.CommandLineResult
+ errors []*ast.Diagnostic
+ statistics tsc.Statistics
+ programStats []*tsc.Statistics
+ filesToDelete []string
+}
+
+func (b *orchestratorResult) report(s *Orchestrator) {
+ tsc.CreateReportErrorSummary(s.opts.Sys, s.opts.Command.CompilerOptions)(b.errors)
+ if b.filesToDelete != nil {
+ s.createBuilderStatusReporter(nil)(
+ ast.NewCompilerDiagnostic(
+ diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0,
+ strings.Join(core.Map(b.filesToDelete, func(f string) string {
+ return "\r\n * " + f
+ }), ""),
+ ))
+ }
+ if len(b.programStats) == 0 {
+ return
+ }
+ if !s.opts.Command.CompilerOptions.Diagnostics.IsTrue() && !s.opts.Command.CompilerOptions.ExtendedDiagnostics.IsTrue() {
+ return
+ }
+ b.statistics.Aggregate(b.programStats, s.opts.Sys.SinceStart())
+ b.statistics.Report(s.opts.Sys.Writer(), s.opts.Testing)
+}
+
+type Orchestrator struct {
+ opts Options
+ comparePathsOptions tspath.ComparePathsOptions
+ host *host
+
+ // order generation result
+ tasks collections.SyncMap[tspath.Path, *buildTask]
+ order []string
+ errors []*ast.Diagnostic
+}
+
+func (o *Orchestrator) relativeFileName(fileName string) string {
+ return tspath.ConvertToRelativePath(fileName, o.comparePathsOptions)
+}
+
+func (o *Orchestrator) toPath(fileName string) tspath.Path {
+ return tspath.ToPath(fileName, o.comparePathsOptions.CurrentDirectory, o.comparePathsOptions.UseCaseSensitiveFileNames)
+}
+
+func (o *Orchestrator) Order() []string {
+ return o.order
+}
+
+func (o *Orchestrator) Upstream(configName string) []string {
+ path := o.toPath(configName)
+ task, ok := o.tasks.Load(path)
+ if !ok {
+ panic("No build task found for " + configName)
+ }
+ return core.Map(task.upStream, func(t *buildTask) string {
+ return t.config
+ })
+}
+
+func (o *Orchestrator) createBuildTasks(configs []string, wg core.WorkGroup) {
+ for _, config := range configs {
+ wg.Queue(func() {
+ path := o.toPath(config)
+ task := &buildTask{config: config}
+ if _, loaded := o.tasks.LoadOrStore(path, task); loaded {
+ return
+ }
+ task.resolved = o.host.GetResolvedProjectReference(config, path)
+ if task.resolved != nil {
+ o.createBuildTasks(task.resolved.ResolvedProjectReferencePaths(), wg)
+ }
+ })
+ }
+}
+
+func (o *Orchestrator) setupBuildTask(
+ configName string,
+ inCircularContext bool,
+ completed *collections.Set[tspath.Path],
+ analyzing *collections.Set[tspath.Path],
+ circularityStack []string,
+) *buildTask {
+ path := o.toPath(configName)
+ task, ok := o.tasks.Load(path)
+ if !ok {
+ panic("No build task found for " + configName)
+ }
+ if !completed.Has(path) {
+ if analyzing.Has(path) {
+ if !inCircularContext {
+ o.errors = append(o.errors, ast.NewCompilerDiagnostic(
+ diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0,
+ strings.Join(circularityStack, "\n"),
+ ))
+ }
+ return nil
+ }
+ analyzing.Add(path)
+ circularityStack = append(circularityStack, configName)
+ if task.resolved != nil {
+ for index, subReference := range task.resolved.ResolvedProjectReferencePaths() {
+ upstream := o.setupBuildTask(subReference, inCircularContext || task.resolved.ProjectReferences()[index].Circular, completed, analyzing, circularityStack)
+ if upstream != nil {
+ task.upStream = append(task.upStream, upstream)
+ }
+ }
+ }
+ circularityStack = circularityStack[:len(circularityStack)-1]
+ completed.Add(path)
+ task.reportDone = make(chan struct{})
+ prev := core.LastOrNil(o.order)
+ if prev != "" {
+ if prevTask, ok := o.tasks.Load(o.toPath(prev)); ok {
+ task.prevReporter = prevTask
+ } else {
+ panic("No previous task found for " + prev)
+ }
+ }
+ task.done = make(chan struct{})
+ o.order = append(o.order, configName)
+ }
+ return task
+}
+
+func (o *Orchestrator) GenerateGraph() {
+ o.host = &host{
+ builder: o,
+ host: compiler.NewCachedFSCompilerHost(o.opts.Sys.GetCurrentDirectory(), o.opts.Sys.FS(), o.opts.Sys.DefaultLibraryPath(), nil, nil),
+ }
+
+ projects := o.opts.Command.ResolvedProjectPaths()
+ // Parse all config files in parallel
+ wg := core.NewWorkGroup(o.opts.Command.CompilerOptions.SingleThreaded.IsTrue())
+ o.createBuildTasks(projects, wg)
+ wg.RunAndWait()
+
+ // Generate the graph
+ completed := collections.Set[tspath.Path]{}
+ analyzing := collections.Set[tspath.Path]{}
+ circularityStack := []string{}
+ for _, project := range projects {
+ o.setupBuildTask(project, false, &completed, &analyzing, circularityStack)
+ }
+}
+
+func (o *Orchestrator) Start() tsc.CommandLineResult {
+ o.GenerateGraph()
+ build := !o.opts.Command.BuildOptions.Clean.IsTrue()
+ if build && o.opts.Command.BuildOptions.Verbose.IsTrue() {
+ o.createBuilderStatusReporter(nil)(ast.NewCompilerDiagnostic(
+ diagnostics.Projects_in_this_build_Colon_0,
+ strings.Join(core.Map(o.Order(), func(p string) string {
+ return "\r\n * " + o.relativeFileName(p)
+ }), ""),
+ ))
+ }
+ var buildResult orchestratorResult
+ if len(o.errors) == 0 {
+ wg := core.NewWorkGroup(o.opts.Command.CompilerOptions.SingleThreaded.IsTrue())
+ o.tasks.Range(func(path tspath.Path, task *buildTask) bool {
+ task.reportStatus = o.createBuilderStatusReporter(task)
+ task.diagnosticReporter = o.createDiagnosticReporter(task)
+ wg.Queue(func() {
+ if build {
+ task.buildProject(o, path)
+ } else {
+ task.cleanProject(o, path)
+ }
+ task.report(o, path, &buildResult)
+ })
+ return true
+ })
+ wg.RunAndWait()
+ buildResult.statistics.Projects = len(o.Order())
+ } else {
+ buildResult.result.Status = tsc.ExitStatusProjectReferenceCycle_OutputsSkipped
+ reportDiagnostic := o.createDiagnosticReporter(nil)
+ for _, err := range o.errors {
+ reportDiagnostic(err)
+ }
+ buildResult.errors = o.errors
+ }
+ buildResult.report(o)
+ return buildResult.result
+}
+
+func (o *Orchestrator) getWriter(task *buildTask) io.Writer {
+ if task == nil {
+ return o.opts.Sys.Writer()
+ }
+ return &task.builder
+}
+
+func (o *Orchestrator) createBuilderStatusReporter(task *buildTask) tsc.DiagnosticReporter {
+ return tsc.CreateBuilderStatusReporter(o.opts.Sys, o.getWriter(task), o.opts.Command.CompilerOptions, o.opts.Testing)
+}
+
+func (o *Orchestrator) createDiagnosticReporter(task *buildTask) tsc.DiagnosticReporter {
+ return tsc.CreateDiagnosticReporter(o.opts.Sys, o.getWriter(task), o.opts.Command.CompilerOptions)
+}
+
+func NewOrchestrator(opts Options) *Orchestrator {
+ return &Orchestrator{
+ opts: opts,
+ comparePathsOptions: tspath.ComparePathsOptions{
+ CurrentDirectory: opts.Sys.GetCurrentDirectory(),
+ UseCaseSensitiveFileNames: opts.Sys.FS().UseCaseSensitiveFileNames(),
+ },
+ }
+}
diff --git a/internal/execute/build/uptodatestatus.go b/internal/execute/build/uptodatestatus.go
new file mode 100644
index 0000000000..8d6218b2f9
--- /dev/null
+++ b/internal/execute/build/uptodatestatus.go
@@ -0,0 +1,107 @@
+package build
+
+import "time"
+
+type upToDateStatusType uint16
+
+const (
+ // Errors:
+
+ // config file was not found
+ upToDateStatusTypeConfigFileNotFound upToDateStatusType = iota
+ // found errors during build
+ upToDateStatusTypeBuildErrors
+ // did not build because upstream project has errors - and we have option to stop build on upstream errors
+ upToDateStatusTypeUpstreamErrors
+
+ // Its all good, no work to do
+ upToDateStatusTypeUpToDate
+
+ // Pseudo-builds - touch timestamps, no actual build:
+
+ // The project appears out of date because its upstream inputs are newer than its outputs,
+ // but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs.
+ // This means we can Pseudo-build (just touch timestamps), as if we had actually built this project.
+ upToDateStatusTypeUpToDateWithUpstreamTypes
+ // The project appears up to date and even though input file changed, its text didnt so just need to update timestamps
+ upToDateStatusTypeUpToDateWithInputFileText
+
+ // Needs build:
+
+ // input file is missing
+ upToDateStatusTypeInputFileMissing
+ // output file is missing
+ upToDateStatusTypeOutputMissing
+ // input file is newer than output file
+ upToDateStatusTypeInputFileNewer
+ // build info is out of date as we need to emit some files
+ upToDateStatusTypeOutOfDateBuildInfoWithPendingEmit
+ // build info indiscates that project has errors and they need to be reported
+ upToDateStatusTypeOutOfDateBuildInfoWithErrors
+ // build info options indicate there is work to do based on changes in options
+ upToDateStatusTypeOutOfDateOptions
+ // file was root when built but not any more
+ upToDateStatusTypeOutOfDateRoots
+ // buildInfo.version mismatch with current ts version
+ upToDateStatusTypeTsVersionOutputOfDate
+ // build because --force was specified
+ upToDateStatusTypeForceBuild
+
+ // solution file
+ upToDateStatusTypeSolution
+)
+
+type inputOutputName struct {
+ input string
+ output string
+}
+
+type fileAndTime struct {
+ file string
+ time time.Time
+}
+
+type inputOutputFileAndTime struct {
+ input fileAndTime
+ output fileAndTime
+ buildInfo string
+}
+
+type upstreamErrors struct {
+ ref string
+ refHasUpstreamErrors bool
+}
+
+type upToDateStatus struct {
+ kind upToDateStatusType
+ data any
+}
+
+func (s *upToDateStatus) isError() bool {
+ switch s.kind {
+ case upToDateStatusTypeConfigFileNotFound,
+ upToDateStatusTypeBuildErrors,
+ upToDateStatusTypeUpstreamErrors:
+ return true
+ default:
+ return false
+ }
+}
+
+func (s *upToDateStatus) isPseudoBuild() bool {
+ switch s.kind {
+ case upToDateStatusTypeUpToDateWithUpstreamTypes,
+ upToDateStatusTypeUpToDateWithInputFileText:
+ return true
+ default:
+ return false
+ }
+}
+
+func (s *upToDateStatus) inputOutputFileAndTime() *inputOutputFileAndTime {
+ data, ok := s.data.(*inputOutputFileAndTime)
+ if !ok {
+ return nil
+ }
+ return data
+}
diff --git a/internal/incremental/affectedfileshandler.go b/internal/execute/incremental/affectedfileshandler.go
similarity index 100%
rename from internal/incremental/affectedfileshandler.go
rename to internal/execute/incremental/affectedfileshandler.go
diff --git a/internal/incremental/buildInfo.go b/internal/execute/incremental/buildInfo.go
similarity index 60%
rename from internal/incremental/buildInfo.go
rename to internal/execute/incremental/buildInfo.go
index bf537e0084..ab5b622363 100644
--- a/internal/incremental/buildInfo.go
+++ b/internal/execute/incremental/buildInfo.go
@@ -2,6 +2,7 @@ package incremental
import (
"fmt"
+ "iter"
"github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
@@ -17,52 +18,56 @@ type (
BuildInfoFileIdListId int
)
-// /**
-// * buildInfoRoot is
-// * for incremental program buildinfo
-// * - start and end of FileId for consecutive fileIds to be included as root
-// * - single fileId that is root
-// * for non incremental program buildinfo
-// * - string that is the root file name
-// */
-// type BuildInfoRoot struct {
-// StartEnd *[2]BuildInfoFileId
-// Single BuildInfoFileId
-// nonIncremental string
-// }
-
-// func (o BuildInfoRoot) MarshalJSON() ([]byte, error) {
-// if o.StartEnd != nil {
-// return json.Marshal(o.StartEnd)
-// }
-// if o.Single != 0 {
-// return json.Marshal(o.Single)
-// }
-// if o.nonIncremental != "" {
-// return json.Marshal(o.nonIncremental)
-// }
-// panic("unknown BuildInfoRoot type")
-// }
-
-// func (o *BuildInfoRoot) UnmarshalJSON(data []byte) error {
-// *o = BuildInfoRoot{}
-// var vStartEnd [2]BuildInfoFileId
-// if err := json.Unmarshal(data, &vStartEnd); err == nil {
-// o.StartEnd = &vStartEnd
-// return nil
-// }
-// var vSingle BuildInfoFileId
-// if err := json.Unmarshal(data, &vSingle); err == nil {
-// o.Single = vSingle
-// return nil
-// }
-// var vNonIncremental string
-// if err := json.Unmarshal(data, &vNonIncremental); err == nil {
-// o.nonIncremental = vNonIncremental
-// return nil
-// }
-// return fmt.Errorf("invalid BuildInfoRoot: %s", data)
-// }
+// buildInfoRoot is
+// - for incremental program buildinfo
+// - start and end of FileId for consecutive fileIds to be included as root
+// - start - single fileId that is root
+//
+// - for non incremental program buildinfo
+// - string that is the root file name
+type BuildInfoRoot struct {
+ Start BuildInfoFileId
+ End BuildInfoFileId
+ NonIncremental string // Root of a non incremental program
+}
+
+func (b *BuildInfoRoot) MarshalJSON() ([]byte, error) {
+ if b.Start != 0 {
+ if b.End != 0 {
+ return json.Marshal([2]BuildInfoFileId{b.Start, b.End})
+ } else {
+ return json.Marshal(b.Start)
+ }
+ } else {
+ return json.Marshal(b.NonIncremental)
+ }
+}
+
+func (b *BuildInfoRoot) UnmarshalJSON(data []byte) error {
+ var startAndEnd *[2]int
+ if err := json.Unmarshal(data, &startAndEnd); err != nil {
+ var start int
+ if err := json.Unmarshal(data, &start); err != nil {
+ var name string
+ if err := json.Unmarshal(data, &name); err != nil {
+ return fmt.Errorf("invalid BuildInfoRoot: %s", data)
+ }
+ *b = BuildInfoRoot{
+ NonIncremental: name,
+ }
+ return nil
+ }
+ *b = BuildInfoRoot{
+ Start: BuildInfoFileId(start),
+ }
+ return nil
+ }
+ *b = BuildInfoRoot{
+ Start: BuildInfoFileId(startAndEnd[0]),
+ End: BuildInfoFileId(startAndEnd[1]),
+ }
+ return nil
+}
type buildInfoFileInfoNoSignature struct {
Version string `json:"version,omitzero"`
@@ -109,6 +114,9 @@ func newBuildInfoFileInfo(fileInfo *fileInfo) *BuildInfoFileInfo {
}
func (b *BuildInfoFileInfo) GetFileInfo() *fileInfo {
+ if b == nil {
+ return nil
+ }
if b.signature != "" {
return &fileInfo{
version: b.signature,
@@ -147,20 +155,20 @@ func (b *BuildInfoFileInfo) MarshalJSON() ([]byte, error) {
func (b *BuildInfoFileInfo) UnmarshalJSON(data []byte) error {
var vSignature string
- if err := json.Unmarshal(data, &vSignature); err == nil {
- *b = BuildInfoFileInfo{signature: vSignature}
- return nil
- }
- var noSignature buildInfoFileInfoNoSignature
- if err := json.Unmarshal(data, &noSignature); err == nil && noSignature.NoSignature {
+ if err := json.Unmarshal(data, &vSignature); err != nil {
+ var noSignature buildInfoFileInfoNoSignature
+ if err := json.Unmarshal(data, &noSignature); err != nil || !noSignature.NoSignature {
+ var fileInfo buildInfoFileInfoWithSignature
+ if err := json.Unmarshal(data, &fileInfo); err != nil {
+ return fmt.Errorf("invalid BuildInfoFileInfo: %s", data)
+ }
+ *b = BuildInfoFileInfo{fileInfo: &fileInfo}
+ return nil
+ }
*b = BuildInfoFileInfo{noSignature: &noSignature}
return nil
}
- var fileInfo buildInfoFileInfoWithSignature
- if err := json.Unmarshal(data, &fileInfo); err != nil {
- return fmt.Errorf("invalid BuildInfoFileInfo: %s", data)
- }
- *b = BuildInfoFileInfo{fileInfo: &fileInfo}
+ *b = BuildInfoFileInfo{signature: vSignature}
return nil
}
@@ -251,20 +259,20 @@ func (b *BuildInfoSemanticDiagnostic) MarshalJSON() ([]byte, error) {
func (b *BuildInfoSemanticDiagnostic) UnmarshalJSON(data []byte) error {
var fileId BuildInfoFileId
- if err := json.Unmarshal(data, &fileId); err == nil {
- *b = BuildInfoSemanticDiagnostic{
- FileId: fileId,
+ if err := json.Unmarshal(data, &fileId); err != nil {
+ var diagnostics BuildInfoDiagnosticsOfFile
+ if err := json.Unmarshal(data, &diagnostics); err != nil {
+ return fmt.Errorf("invalid BuildInfoSemanticDiagnostic: %s", data)
}
- return nil
- }
- var diagnostics BuildInfoDiagnosticsOfFile
- if err := json.Unmarshal(data, &diagnostics); err == nil {
*b = BuildInfoSemanticDiagnostic{
Diagnostics: &diagnostics,
}
return nil
}
- return fmt.Errorf("invalid BuildInfoSemanticDiagnostic: %s", data)
+ *b = BuildInfoSemanticDiagnostic{
+ FileId: fileId,
+ }
+ return nil
}
// fileId if pending emit is same as what compilerOptions suggest
@@ -289,30 +297,32 @@ func (b *BuildInfoFilePendingEmit) MarshalJSON() ([]byte, error) {
func (b *BuildInfoFilePendingEmit) UnmarshalJSON(data []byte) error {
var fileId BuildInfoFileId
- if err := json.Unmarshal(data, &fileId); err == nil {
- *b = BuildInfoFilePendingEmit{
- FileId: fileId,
+ if err := json.Unmarshal(data, &fileId); err != nil {
+ var intTuple []int
+ if err := json.Unmarshal(data, &intTuple); err != nil || len(intTuple) == 0 {
+ return fmt.Errorf("invalid BuildInfoFilePendingEmit: %s", data)
}
- return nil
- }
- var intTuple []int
- if err := json.Unmarshal(data, &intTuple); err == nil {
- if len(intTuple) == 1 {
+ switch len(intTuple) {
+ case 1:
*b = BuildInfoFilePendingEmit{
FileId: BuildInfoFileId(intTuple[0]),
EmitKind: FileEmitKindDts,
}
return nil
- } else if len(intTuple) == 2 {
+ case 2:
*b = BuildInfoFilePendingEmit{
FileId: BuildInfoFileId(intTuple[0]),
EmitKind: FileEmitKind(intTuple[1]),
}
return nil
+ default:
+ return fmt.Errorf("invalid BuildInfoFilePendingEmit: expected 1 or 2 integers, got %d", len(intTuple))
}
- return fmt.Errorf("invalid BuildInfoFilePendingEmit: expected 1 or 2 integers, got %d", len(intTuple))
}
- return fmt.Errorf("invalid BuildInfoFilePendingEmit: %s", data)
+ *b = BuildInfoFilePendingEmit{
+ FileId: fileId,
+ }
+ return nil
}
// [fileId, signature] if different from file's signature
@@ -367,59 +377,86 @@ func (b *BuildInfoEmitSignature) MarshalJSON() ([]byte, error) {
func (b *BuildInfoEmitSignature) UnmarshalJSON(data []byte) error {
var fileId BuildInfoFileId
- if err := json.Unmarshal(data, &fileId); err == nil {
- *b = BuildInfoEmitSignature{
- FileId: fileId,
+ if err := json.Unmarshal(data, &fileId); err != nil {
+ var fileIdAndSignature []any
+ if err := json.Unmarshal(data, &fileIdAndSignature); err != nil {
+ return fmt.Errorf("invalid BuildInfoEmitSignature: %s", data)
}
- return nil
- }
- var fileIdAndSignature []any
- if err := json.Unmarshal(data, &fileIdAndSignature); err == nil {
- if len(fileIdAndSignature) == 2 {
- var fileId BuildInfoFileId
- if id, ok := fileIdAndSignature[0].(float64); ok {
- fileId = BuildInfoFileId(id)
+ if len(fileIdAndSignature) != 2 {
+ return fmt.Errorf("invalid BuildInfoEmitSignature: expected 2 elements, got %d", len(fileIdAndSignature))
+ }
+ var fileId BuildInfoFileId
+ if id, ok := fileIdAndSignature[0].(float64); !ok {
+ return fmt.Errorf("invalid fileId in BuildInfoEmitSignature: expected float64, got %T", fileIdAndSignature[0])
+ } else {
+ fileId = BuildInfoFileId(id)
+ }
+ var signature string
+ var differsOnlyInDtsMap, differsInOptions bool
+ if signatureV, ok := fileIdAndSignature[1].(string); !ok {
+ if signatureList, ok := fileIdAndSignature[1].([]any); !ok {
+ return fmt.Errorf("invalid signature in BuildInfoEmitSignature: expected string or []string, got %T", fileIdAndSignature[1])
} else {
- return fmt.Errorf("invalid fileId in BuildInfoEmitSignature: expected float64, got %T", fileIdAndSignature[0])
- }
- var signature string
- var differsOnlyInDtsMap, differsInOptions bool
- if signatureV, ok := fileIdAndSignature[1].(string); !ok {
- if signatureList, ok := fileIdAndSignature[1].([]string); ok {
- if len(signatureList) == 0 {
- differsOnlyInDtsMap = true
- } else if len(signatureList) == 1 {
- signature = signatureList[0]
- differsInOptions = true
+ switch len(signatureList) {
+ case 0:
+ differsOnlyInDtsMap = true
+ case 1:
+ if sig, ok := signatureList[0].(string); !ok {
+ return fmt.Errorf("invalid signature in BuildInfoEmitSignature: expected string, got %T", signatureList[0])
} else {
- return fmt.Errorf("invalid signature in BuildInfoEmitSignature: expected string or []string with 0 or 1 element, got %d elements", len(signatureList))
+ signature = sig
+ differsInOptions = true
}
- } else {
- return fmt.Errorf("invalid signature in BuildInfoEmitSignature: expected string or []string, got %T", fileIdAndSignature[1])
+ default:
+ return fmt.Errorf("invalid signature in BuildInfoEmitSignature: expected string or []string with 0 or 1 element, got %d elements", len(signatureList))
}
- } else {
- signature = signatureV
- }
- *b = BuildInfoEmitSignature{
- FileId: fileId,
- Signature: signature,
- DiffersOnlyInDtsMap: differsOnlyInDtsMap,
- DiffersInOptions: differsInOptions,
}
- return nil
+ } else {
+ signature = signatureV
+ }
+ *b = BuildInfoEmitSignature{
+ FileId: fileId,
+ Signature: signature,
+ DiffersOnlyInDtsMap: differsOnlyInDtsMap,
+ DiffersInOptions: differsInOptions,
}
- return fmt.Errorf("invalid BuildInfoEmitSignature: expected 2 elements, got %d", len(fileIdAndSignature))
+ return nil
+
}
- return fmt.Errorf("invalid BuildInfoEmitSignature: %s", data)
+ *b = BuildInfoEmitSignature{
+ FileId: fileId,
+ }
+ return nil
+}
+
+type BuildInfoResolvedRoot struct {
+ Resolved BuildInfoFileId
+ Root BuildInfoFileId
+}
+
+func (b *BuildInfoResolvedRoot) MarshalJSON() ([]byte, error) {
+ return json.Marshal([2]BuildInfoFileId{b.Resolved, b.Root})
+}
+
+func (b *BuildInfoResolvedRoot) UnmarshalJSON(data []byte) error {
+ var resolvedAndRoot [2]int
+ if err := json.Unmarshal(data, &resolvedAndRoot); err != nil {
+ return fmt.Errorf("invalid BuildInfoResolvedRoot: %s", data)
+ }
+ *b = BuildInfoResolvedRoot{
+ Resolved: BuildInfoFileId(resolvedAndRoot[0]),
+ Root: BuildInfoFileId(resolvedAndRoot[1]),
+ }
+ return nil
}
type BuildInfo struct {
Version string `json:"version,omitzero"`
// Common between incremental and tsc -b buildinfo for non incremental programs
- Errors bool `json:"errors,omitzero"`
- CheckPending bool `json:"checkPending,omitzero"`
- // Root []BuildInfoRoot `json:"root,omitzero"`
+ Errors bool `json:"errors,omitzero"`
+ CheckPending bool `json:"checkPending,omitzero"`
+ Root []*BuildInfoRoot `json:"root,omitzero"`
// IncrementalProgram info
FileNames []string `json:"fileNames,omitzero"`
@@ -433,7 +470,10 @@ type BuildInfo struct {
AffectedFilesPendingEmit []*BuildInfoFilePendingEmit `json:"affectedFilesPendingEmit,omitzero"`
LatestChangedDtsFile string `json:"latestChangedDtsFile,omitzero"` // Because this is only output file in the program, we dont need fileId to deduplicate name
EmitSignatures []*BuildInfoEmitSignature `json:"emitSignatures,omitzero"`
- // resolvedRoot: readonly BuildInfoResolvedRoot[] | undefined;
+ ResolvedRoot []*BuildInfoResolvedRoot `json:"resolvedRoot,omitzero"`
+
+ // NonIncrementalProgram info
+ SemanticErrors bool `json:"semanticErrors,omitzero"`
}
func (b *BuildInfo) IsValidVersion() bool {
@@ -444,6 +484,14 @@ func (b *BuildInfo) IsIncremental() bool {
return b != nil && len(b.FileNames) != 0
}
+func (b *BuildInfo) fileName(fileId BuildInfoFileId) string {
+ return b.FileNames[fileId-1]
+}
+
+func (b *BuildInfo) fileInfo(fileId BuildInfoFileId) *BuildInfoFileInfo {
+ return b.FileInfos[fileId-1]
+}
+
func (b *BuildInfo) GetCompilerOptions(buildInfoDirectory string) *core.CompilerOptions {
options := &core.CompilerOptions{}
for option, value := range b.Options.Entries() {
@@ -459,3 +507,78 @@ func (b *BuildInfo) GetCompilerOptions(buildInfoDirectory string) *core.Compiler
}
return options
}
+
+func (b *BuildInfo) IsEmitPending(resolved *tsoptions.ParsedCommandLine, buildInfoDirectory string) bool {
+ // Some of the emit files like source map or dts etc are not yet done
+ if !resolved.CompilerOptions().NoEmit.IsTrue() || resolved.CompilerOptions().GetEmitDeclarations() {
+ pendingEmit := getPendingEmitKindWithOptions(resolved.CompilerOptions(), b.GetCompilerOptions(buildInfoDirectory))
+ if resolved.CompilerOptions().NoEmit.IsTrue() {
+ pendingEmit &= FileEmitKindDtsErrors
+ }
+ return pendingEmit != 0
+ }
+ return false
+}
+
+func (b *BuildInfo) GetBuildInfoRootInfoReader(buildInfoDirectory string, comparePathOptions tspath.ComparePathsOptions) *BuildInfoRootInfoReader {
+ resolvedRootFileInfos := make(map[tspath.Path]*BuildInfoFileInfo, len(b.FileNames))
+ // Roots of the File
+ rootToResolved := collections.NewOrderedMapWithSizeHint[tspath.Path, tspath.Path](len(b.FileNames))
+ resolvedToRoot := make(map[tspath.Path]tspath.Path, len(b.ResolvedRoot))
+ toPath := func(fileName string) tspath.Path {
+ return tspath.ToPath(fileName, buildInfoDirectory, comparePathOptions.UseCaseSensitiveFileNames)
+ }
+
+ // Create map from resolvedRoot to Root
+ for _, resolved := range b.ResolvedRoot {
+ resolvedToRoot[toPath(b.fileName(resolved.Resolved))] = toPath(b.fileName(resolved.Root))
+ }
+
+ addRoot := func(resolvedRoot string, fileInfo *BuildInfoFileInfo) {
+ resolvedRootPath := toPath(resolvedRoot)
+ if rootPath, ok := resolvedToRoot[resolvedRootPath]; ok {
+ rootToResolved.Set(rootPath, resolvedRootPath)
+ } else {
+ rootToResolved.Set(resolvedRootPath, resolvedRootPath)
+ }
+ if fileInfo != nil {
+ resolvedRootFileInfos[resolvedRootPath] = fileInfo
+ }
+ }
+
+ for _, root := range b.Root {
+ if root.NonIncremental != "" {
+ addRoot(root.NonIncremental, nil)
+ } else if root.End == 0 {
+ addRoot(b.fileName(root.Start), b.fileInfo(root.Start))
+ } else {
+ for i := root.Start; i <= root.End; i++ {
+ addRoot(b.fileName(i), b.fileInfo(i))
+ }
+ }
+ }
+
+ return &BuildInfoRootInfoReader{
+ resolvedRootFileInfos: resolvedRootFileInfos,
+ rootToResolved: rootToResolved,
+ }
+}
+
+type BuildInfoRootInfoReader struct {
+ resolvedRootFileInfos map[tspath.Path]*BuildInfoFileInfo
+ rootToResolved *collections.OrderedMap[tspath.Path, tspath.Path]
+}
+
+func (b *BuildInfoRootInfoReader) GetBuildInfoFileInfo(inputFilePath tspath.Path) (*BuildInfoFileInfo, tspath.Path) {
+ if info, ok := b.resolvedRootFileInfos[inputFilePath]; ok {
+ return info, inputFilePath
+ }
+ if resolved, ok := b.rootToResolved.Get(inputFilePath); ok {
+ return b.resolvedRootFileInfos[resolved], resolved
+ }
+ return nil, ""
+}
+
+func (b *BuildInfoRootInfoReader) Roots() iter.Seq[tspath.Path] {
+ return b.rootToResolved.Keys()
+}
diff --git a/internal/incremental/buildinfotosnapshot.go b/internal/execute/incremental/buildinfotosnapshot.go
similarity index 99%
rename from internal/incremental/buildinfotosnapshot.go
rename to internal/execute/incremental/buildinfotosnapshot.go
index 67a49c0cea..309ed32c95 100644
--- a/internal/incremental/buildinfotosnapshot.go
+++ b/internal/execute/incremental/buildinfotosnapshot.go
@@ -41,6 +41,7 @@ func buildInfoToSnapshot(buildInfo *BuildInfo, buildInfoFileName string, config
to.snapshot.latestChangedDtsFile = to.toAbsolutePath(buildInfo.LatestChangedDtsFile)
}
to.snapshot.hasErrors = core.IfElse(buildInfo.Errors, core.TSTrue, core.TSFalse)
+ to.snapshot.hasSemanticErrors = buildInfo.SemanticErrors
to.snapshot.checkPending = buildInfo.CheckPending
return &to.snapshot
}
diff --git a/internal/incremental/emitfileshandler.go b/internal/execute/incremental/emitfileshandler.go
similarity index 83%
rename from internal/incremental/emitfileshandler.go
rename to internal/execute/incremental/emitfileshandler.go
index 6f2937815b..9ff05cfe19 100644
--- a/internal/incremental/emitfileshandler.go
+++ b/internal/execute/incremental/emitfileshandler.go
@@ -2,7 +2,7 @@ package incremental
import (
"context"
- "slices"
+ "time"
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/collections"
@@ -22,7 +22,7 @@ type emitFilesHandler struct {
isForDtsErrors bool
signatures collections.SyncMap[tspath.Path, string]
emitSignatures collections.SyncMap[tspath.Path, *emitSignature]
- latestChangedDtsFiles collections.SyncSet[string]
+ latestChangedDtsFiles collections.SyncMap[tspath.Path, string]
deletedPendingKinds collections.Set[tspath.Path]
emitUpdates collections.SyncMap[tspath.Path, *emitUpdate]
}
@@ -147,6 +147,7 @@ func (h *emitFilesHandler) getEmitOptions(options compiler.EmitOptions) compiler
TargetSourceFile: options.TargetSourceFile,
EmitOnly: options.EmitOnly,
WriteFile: func(fileName string, text string, writeByteOrderMark bool, data *compiler.WriteFileData) error {
+ var differsOnlyInMap bool
if tspath.IsDeclarationFileName(fileName) {
var emitSignature string
info, _ := h.program.snapshot.fileInfos.Load(options.TargetSourceFile.Path())
@@ -164,22 +165,33 @@ func (h *emitFilesHandler) getEmitOptions(options compiler.EmitOptions) compiler
// Store d.ts emit hash so later can be compared to check if d.ts has changed.
// Currently we do this only for composite projects since these are the only projects that can be referenced by other projects
// and would need their d.ts change time in --build mode
- if h.skipDtsOutputOfComposite(options.TargetSourceFile, fileName, text, data, emitSignature) {
+ if h.skipDtsOutputOfComposite(options.TargetSourceFile, fileName, text, data, emitSignature, &differsOnlyInMap) {
return nil
}
}
+ var aTime time.Time
+ if differsOnlyInMap {
+ aTime = h.program.host.GetMTime(fileName)
+ }
+ var err error
if options.WriteFile != nil {
- return options.WriteFile(fileName, text, writeByteOrderMark, data)
+ err = options.WriteFile(fileName, text, writeByteOrderMark, data)
+ } else {
+ err = h.program.program.Host().FS().WriteFile(fileName, text, writeByteOrderMark)
+ }
+ if err != nil && differsOnlyInMap {
+ // Revert the time to original one
+ err = h.program.host.SetMTime(fileName, aTime)
}
- return h.program.program.Host().FS().WriteFile(fileName, text, writeByteOrderMark)
+ return err
},
}
}
// Compare to existing computed signature and store it or handle the changes in d.ts map option from before
// returning undefined means that, we dont need to emit this d.ts file since its contents didnt change
-func (h *emitFilesHandler) skipDtsOutputOfComposite(file *ast.SourceFile, outputFileName string, text string, data *compiler.WriteFileData, newSignature string) bool {
+func (h *emitFilesHandler) skipDtsOutputOfComposite(file *ast.SourceFile, outputFileName string, text string, data *compiler.WriteFileData, newSignature string, differsOnlyInMap *bool) bool {
if !h.program.snapshot.options.Composite.IsTrue() {
return false
}
@@ -202,12 +214,12 @@ func (h *emitFilesHandler) skipDtsOutputOfComposite(file *ast.SourceFile, output
data.SkippedDtsWrite = true
return true
} else {
- // Mark as differsOnlyInMap so that --build can reverse the timestamp so that
+ // Mark as differsOnlyInMap so that we can reverse the timestamp with --build so that
// the downstream projects dont detect this as change in d.ts file
- data.DiffersOnlyInMap = true
+ *differsOnlyInMap = h.program.Options().Build.IsTrue()
}
} else {
- h.latestChangedDtsFiles.Add(outputFileName)
+ h.latestChangedDtsFiles.Store(file.Path(), outputFileName)
}
h.emitSignatures.Store(file.Path(), &emitSignature{signature: newSignature})
return false
@@ -228,32 +240,32 @@ func (h *emitFilesHandler) updateSnapshot() []*compiler.EmitResult {
h.program.snapshot.buildInfoEmitPending.Store(true)
return true
})
- latestChangedDtsFiles := h.latestChangedDtsFiles.ToSlice()
- slices.Sort(latestChangedDtsFiles)
- if latestChangedDtsFile := core.LastOrNil(latestChangedDtsFiles); latestChangedDtsFile != "" {
- h.program.snapshot.latestChangedDtsFile = latestChangedDtsFile
- h.program.snapshot.buildInfoEmitPending.Store(true)
- }
for file := range h.deletedPendingKinds.Keys() {
h.program.snapshot.affectedFilesPendingEmit.Delete(file)
h.program.snapshot.buildInfoEmitPending.Store(true)
}
+ // Always use correct order when to collect the result
var results []*compiler.EmitResult
- h.emitUpdates.Range(func(file tspath.Path, update *emitUpdate) bool {
- if update.pendingKind == 0 {
- h.program.snapshot.affectedFilesPendingEmit.Delete(file)
- } else {
- h.program.snapshot.affectedFilesPendingEmit.Store(file, update.pendingKind)
+ for _, file := range h.program.GetSourceFiles() {
+ if latestChangedDtsFile, ok := h.latestChangedDtsFiles.Load(file.Path()); ok {
+ h.program.snapshot.latestChangedDtsFile = latestChangedDtsFile
+ h.program.snapshot.buildInfoEmitPending.Store(true)
}
- if update.result != nil {
- results = append(results, update.result)
- if len(update.result.Diagnostics) != 0 {
- h.program.snapshot.emitDiagnosticsPerFile.Store(file, &diagnosticsOrBuildInfoDiagnosticsWithFileName{diagnostics: update.result.Diagnostics})
+ if update, ok := h.emitUpdates.Load(file.Path()); ok {
+ if update.pendingKind == 0 {
+ h.program.snapshot.affectedFilesPendingEmit.Delete(file.Path())
+ } else {
+ h.program.snapshot.affectedFilesPendingEmit.Store(file.Path(), update.pendingKind)
}
+ if update.result != nil {
+ results = append(results, update.result)
+ if len(update.result.Diagnostics) != 0 {
+ h.program.snapshot.emitDiagnosticsPerFile.Store(file.Path(), &diagnosticsOrBuildInfoDiagnosticsWithFileName{diagnostics: update.result.Diagnostics})
+ }
+ }
+ h.program.snapshot.buildInfoEmitPending.Store(true)
}
- h.program.snapshot.buildInfoEmitPending.Store(true)
- return true
- })
+ }
return results
}
diff --git a/internal/incremental/incremental.go b/internal/execute/incremental/incremental.go
similarity index 100%
rename from internal/incremental/incremental.go
rename to internal/execute/incremental/incremental.go
diff --git a/internal/incremental/program.go b/internal/execute/incremental/program.go
similarity index 88%
rename from internal/incremental/program.go
rename to internal/execute/incremental/program.go
index 362cea8a3c..09c50e7d19 100644
--- a/internal/incremental/program.go
+++ b/internal/execute/incremental/program.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"slices"
+ "time"
"github.com/go-json-experiment/json"
"github.com/microsoft/typescript-go/internal/ast"
@@ -23,19 +24,26 @@ const (
SignatureUpdateKindUsedVersion
)
+type BuildHost interface {
+ GetMTime(fileName string) time.Time
+ SetMTime(fileName string, mTime time.Time) error
+}
+
type Program struct {
snapshot *snapshot
program *compiler.Program
semanticDiagnosticsPerFile *collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName]
updatedSignatureKinds map[tspath.Path]SignatureUpdateKind
+ host BuildHost
}
var _ compiler.ProgramLike = (*Program)(nil)
-func NewProgram(program *compiler.Program, oldProgram *Program, testing bool) *Program {
+func NewProgram(program *compiler.Program, oldProgram *Program, buildHost BuildHost, testing bool) *Program {
incrementalProgram := &Program{
snapshot: programToSnapshot(program, oldProgram, testing),
program: program,
+ host: buildHost,
}
if testing {
@@ -186,7 +194,7 @@ func (p *Program) Emit(ctx context.Context, options compiler.EmitOptions) *compi
// Emit buildInfo and combine result
buildInfoResult := p.emitBuildInfo(ctx, options)
- if buildInfoResult != nil && buildInfoResult.EmittedFiles != nil {
+ if buildInfoResult != nil {
result.Diagnostics = append(result.Diagnostics, buildInfoResult.Diagnostics...)
result.EmittedFiles = append(result.EmittedFiles, buildInfoResult.EmittedFiles...)
}
@@ -249,8 +257,8 @@ func (p *Program) emitBuildInfo(ctx context.Context, options compiler.EmitOption
return nil
}
if p.snapshot.hasErrors == core.TSUnknown {
- p.snapshot.hasErrors = p.ensureHasErrorsForState(ctx, p.program)
- if p.snapshot.hasErrors != p.snapshot.hasErrorsFromOldState {
+ p.ensureHasErrorsForState(ctx, p.program)
+ if p.snapshot.hasErrors != p.snapshot.hasErrorsFromOldState || p.snapshot.hasSemanticErrors != p.snapshot.hasSemanticErrorsFromOldState {
p.snapshot.buildInfoEmitPending.Store(true)
}
}
@@ -281,18 +289,39 @@ func (p *Program) emitBuildInfo(ctx context.Context, options compiler.EmitOption
}
}
p.snapshot.buildInfoEmitPending.Store(false)
-
- var emittedFiles []string
- if p.snapshot.options.ListEmittedFiles.IsTrue() {
- emittedFiles = []string{buildInfoFileName}
- }
return &compiler.EmitResult{
EmitSkipped: false,
- EmittedFiles: emittedFiles,
+ EmittedFiles: []string{buildInfoFileName},
}
}
-func (p *Program) ensureHasErrorsForState(ctx context.Context, program *compiler.Program) core.Tristate {
+func (p *Program) ensureHasErrorsForState(ctx context.Context, program *compiler.Program) {
+ if slices.ContainsFunc(program.GetSourceFiles(), func(file *ast.SourceFile) bool {
+ if _, ok := p.snapshot.emitDiagnosticsPerFile.Load(file.Path()); ok {
+ // emit diagnostics will be encoded in buildInfo;
+ return true
+ }
+ return false
+ }) {
+ // Record this for only non incremental build info
+ p.snapshot.hasErrors = core.IfElse(p.snapshot.options.IsIncremental(), core.TSFalse, core.TSTrue)
+ // Dont need to encode semantic errors state since the emit diagnostics are encoded
+ p.snapshot.hasSemanticErrors = false
+ return
+ }
+ if len(program.GetConfigFileParsingDiagnostics()) > 0 ||
+ len(program.GetSyntacticDiagnostics(ctx, nil)) > 0 ||
+ len(program.GetProgramDiagnostics()) > 0 ||
+ len(program.GetBindDiagnostics(ctx, nil)) > 0 ||
+ len(program.GetOptionsDiagnostics(ctx)) > 0 ||
+ len(program.GetGlobalDiagnostics(ctx)) > 0 {
+ p.snapshot.hasErrors = core.TSTrue
+ // Dont need to encode semantic errors state since the syntax and program diagnostics are encoded as present
+ p.snapshot.hasSemanticErrors = false
+ return
+ }
+
+ p.snapshot.hasErrors = core.TSFalse
// Check semantic and emit diagnostics first as we dont need to ask program about it
if slices.ContainsFunc(program.GetSourceFiles(), func(file *ast.SourceFile) bool {
semanticDiagnostics, ok := p.snapshot.semanticDiagnosticsPerFile.Load(file.Path())
@@ -304,22 +333,10 @@ func (p *Program) ensureHasErrorsForState(ctx context.Context, program *compiler
// cached semantic diagnostics will be encoded in buildInfo
return true
}
- if _, ok := p.snapshot.emitDiagnosticsPerFile.Load(file.Path()); ok {
- // emit diagnostics will be encoded in buildInfo;
- return true
- }
return false
}) {
// Because semantic diagnostics are recorded in buildInfo, we dont need to encode hasErrors in incremental buildInfo
// But encode as errors in non incremental buildInfo
- return core.IfElse(p.snapshot.options.IsIncremental(), core.TSFalse, core.TSTrue)
- }
- if len(program.GetConfigFileParsingDiagnostics()) > 0 ||
- len(program.GetSyntacticDiagnostics(ctx, nil)) > 0 ||
- len(program.GetBindDiagnostics(ctx, nil)) > 0 ||
- len(program.GetOptionsDiagnostics(ctx)) > 0 {
- return core.TSTrue
- } else {
- return core.TSFalse
+ p.snapshot.hasSemanticErrors = !p.snapshot.options.IsIncremental()
}
}
diff --git a/internal/incremental/programtosnapshot.go b/internal/execute/incremental/programtosnapshot.go
similarity index 99%
rename from internal/incremental/programtosnapshot.go
rename to internal/execute/incremental/programtosnapshot.go
index aa60746f3e..69f8cd5a7e 100644
--- a/internal/incremental/programtosnapshot.go
+++ b/internal/execute/incremental/programtosnapshot.go
@@ -61,6 +61,7 @@ func (t *toProgramSnapshot) reuseFromOldProgram() {
})
t.snapshot.buildInfoEmitPending.Store(t.oldProgram.snapshot.buildInfoEmitPending.Load())
t.snapshot.hasErrorsFromOldState = t.oldProgram.snapshot.hasErrors
+ t.snapshot.hasSemanticErrorsFromOldState = t.oldProgram.snapshot.hasSemanticErrors
} else {
t.snapshot.buildInfoEmitPending.Store(t.snapshot.options.IsIncremental())
}
diff --git a/internal/incremental/referencemap.go b/internal/execute/incremental/referencemap.go
similarity index 100%
rename from internal/incremental/referencemap.go
rename to internal/execute/incremental/referencemap.go
diff --git a/internal/incremental/snapshot.go b/internal/execute/incremental/snapshot.go
similarity index 95%
rename from internal/incremental/snapshot.go
rename to internal/execute/incremental/snapshot.go
index 36db50687c..1fc0222c08 100644
--- a/internal/incremental/snapshot.go
+++ b/internal/execute/incremental/snapshot.go
@@ -28,6 +28,15 @@ func (f *fileInfo) Signature() string { return f.signature
func (f *fileInfo) AffectsGlobalScope() bool { return f.affectsGlobalScope }
func (f *fileInfo) ImpliedNodeFormat() core.ResolutionMode { return f.impliedNodeFormat }
+func ComputeHash(text string, hashWithText bool) string {
+ hashBytes := xxh3.Hash128([]byte(text)).Bytes()
+ hash := hex.EncodeToString(hashBytes[:])
+ if hashWithText {
+ hash += "-" + text
+ }
+ return hash
+}
+
type FileEmitKind uint32
const (
@@ -87,7 +96,7 @@ func getPendingEmitKind(emitKind FileEmitKind, oldEmitKind FileEmitKind) FileEmi
}
// If dts errors pending, add dts errors flag
if (diff & FileEmitKindDtsErrors) != 0 {
- result |= emitKind & FileEmitKindDtsErrors
+ result |= emitKind & FileEmitKindAllDts
}
// If there is diff in Dts emit, pending emit is dts emit flags
if (diff & FileEmitKindAllDtsEmit) != 0 {
@@ -201,9 +210,11 @@ type snapshot struct {
latestChangedDtsFile string
// Hash of d.ts emitted for the file, use to track when emit of d.ts changes
emitSignatures collections.SyncMap[tspath.Path, *emitSignature]
- // Recorded if program had errors
+ // Recorded if program had errors that need to be reported even with --noCheck
hasErrors core.Tristate
- // If semantic diagnsotic check is pending
+ // Recorded if program had semantic errors only for non incremental build
+ hasSemanticErrors bool
+ // If semantic diagnostic check is pending
checkPending bool
// Additional fields that are not serialized but needed to track state
@@ -211,6 +222,7 @@ type snapshot struct {
// true if build info emit is pending
buildInfoEmitPending atomic.Bool
hasErrorsFromOldState core.Tristate
+ hasSemanticErrorsFromOldState bool
allFilesExcludingDefaultLibraryFileOnce sync.Once
// Cache of all files excluding default library file for the current program
allFilesExcludingDefaultLibraryFile []*ast.SourceFile
@@ -227,7 +239,9 @@ func (s *snapshot) addFileToChangeSet(filePath tspath.Path) {
func (s *snapshot) addFileToAffectedFilesPendingEmit(filePath tspath.Path, emitKind FileEmitKind) {
existingKind, _ := s.affectedFilesPendingEmit.Load(filePath)
s.affectedFilesPendingEmit.Store(filePath, existingKind|emitKind)
- s.emitDiagnosticsPerFile.Delete(filePath)
+ if emitKind&FileEmitKindDtsErrors != 0 {
+ s.emitDiagnosticsPerFile.Delete(filePath)
+ }
s.buildInfoEmitPending.Store(true)
}
@@ -295,10 +309,5 @@ func diagnosticToStringBuilder(diagnostic *ast.Diagnostic, file *ast.SourceFile,
}
func (s *snapshot) computeHash(text string) string {
- hashBytes := xxh3.Hash128([]byte(text)).Bytes()
- hash := hex.EncodeToString(hashBytes[:])
- if s.hashWithText {
- hash += "-" + text
- }
- return hash
+ return ComputeHash(text, s.hashWithText)
}
diff --git a/internal/incremental/snapshottobuildinfo.go b/internal/execute/incremental/snapshottobuildinfo.go
similarity index 83%
rename from internal/incremental/snapshottobuildinfo.go
rename to internal/execute/incremental/snapshottobuildinfo.go
index 8fa6dfee5a..22b3e9d1ce 100644
--- a/internal/incremental/snapshottobuildinfo.go
+++ b/internal/execute/incremental/snapshottobuildinfo.go
@@ -26,10 +26,14 @@ func snapshotToBuildInfo(snapshot *snapshot, program *compiler.Program, buildInf
},
fileNameToFileId: make(map[string]BuildInfoFileId),
fileNamesToFileIdListId: make(map[string]BuildInfoFileIdListId),
+ roots: make(map[*ast.SourceFile]tspath.Path),
}
+
to.buildInfo.Version = core.Version()
if snapshot.options.IsIncremental() {
+ to.collectRootFiles()
to.setFileInfoAndEmitSignatures()
+ to.setRootOfIncrementalProgram()
to.setCompilerOptions()
to.setReferencedMap()
to.setChangeFileSet()
@@ -39,13 +43,11 @@ func snapshotToBuildInfo(snapshot *snapshot, program *compiler.Program, buildInf
if snapshot.latestChangedDtsFile != "" {
to.buildInfo.LatestChangedDtsFile = to.relativeToBuildInfo(snapshot.latestChangedDtsFile)
}
+ } else {
+ to.setRootOfNonIncrementalProgram()
}
- // else {
- // const buildInfo: NonIncrementalBuildInfo = {
- // root: arrayFrom(rootFileNames, r => relativeToBuildInfo(r)),
- // };
- // }
to.buildInfo.Errors = snapshot.hasErrors.IsTrue()
+ to.buildInfo.SemanticErrors = snapshot.hasSemanticErrors
to.buildInfo.CheckPending = snapshot.checkPending
return &to.buildInfo
}
@@ -58,6 +60,7 @@ type toBuildInfo struct {
comparePathsOptions tspath.ComparePathsOptions
fileNameToFileId map[string]BuildInfoFileId
fileNamesToFileIdListId map[string]BuildInfoFileIdListId
+ roots map[*ast.SourceFile]tspath.Path
}
func (t *toBuildInfo) relativeToBuildInfo(path string) string {
@@ -174,6 +177,20 @@ func (t *toBuildInfo) toBuildInfoDiagnosticsOfFile(filePath tspath.Path, diags *
return nil
}
+func (t *toBuildInfo) collectRootFiles() {
+ for _, fileName := range t.program.GetRootFileNames() {
+ var file *ast.SourceFile
+ if redirect := t.program.GetParseFileRedirect(fileName); redirect != "" {
+ file = t.program.GetSourceFile(redirect)
+ } else {
+ file = t.program.GetSourceFile(fileName)
+ }
+ if file != nil {
+ t.roots[file] = tspath.ToPath(fileName, t.comparePathsOptions.CurrentDirectory, t.comparePathsOptions.UseCaseSensitiveFileNames)
+ }
+ }
+}
+
func (t *toBuildInfo) setFileInfoAndEmitSignatures() {
t.buildInfo.FileInfos = core.Map(t.program.GetSourceFiles(), func(file *ast.SourceFile) *BuildInfoFileInfo {
info, _ := t.snapshot.fileInfos.Load(file.Path())
@@ -210,6 +227,38 @@ func (t *toBuildInfo) setFileInfoAndEmitSignatures() {
})
}
+func (t *toBuildInfo) setRootOfIncrementalProgram() {
+ keys := slices.Collect(maps.Keys(t.roots))
+ slices.SortFunc(keys, func(a, b *ast.SourceFile) int {
+ return int(t.toFileId(a.Path())) - int(t.toFileId(b.Path()))
+ })
+ for _, file := range keys {
+ root := t.toFileId(t.roots[file])
+ resolved := t.toFileId(file.Path())
+ if t.buildInfo.Root == nil {
+ // First fileId as is
+ t.buildInfo.Root = append(t.buildInfo.Root, &BuildInfoRoot{Start: resolved})
+ } else {
+ last := t.buildInfo.Root[len(t.buildInfo.Root)-1]
+ if last.End == resolved-1 {
+ // If its [..., last = [start, end = fileId - 1]], update last to [start, fileId]
+ last.End = resolved
+ } else if last.End == 0 && last.Start == resolved-1 {
+ // If its [..., last = start = fileId - 1 ], update last to [start, fileId]
+ last.End = resolved
+ } else {
+ t.buildInfo.Root = append(t.buildInfo.Root, &BuildInfoRoot{Start: resolved})
+ }
+ }
+ if root != resolved {
+ t.buildInfo.ResolvedRoot = append(t.buildInfo.ResolvedRoot, &BuildInfoResolvedRoot{
+ Resolved: resolved,
+ Root: root,
+ })
+ }
+ }
+}
+
func (t *toBuildInfo) setCompilerOptions() {
tsoptions.ForEachCompilerOptionValue(
t.snapshot.options,
@@ -293,3 +342,11 @@ func (t *toBuildInfo) setAffectedFilesPendingEmit() {
})
}
}
+
+func (t *toBuildInfo) setRootOfNonIncrementalProgram() {
+ t.buildInfo.Root = core.Map(t.program.GetRootFileNames(), func(fileName string) *BuildInfoRoot {
+ return &BuildInfoRoot{
+ NonIncremental: t.relativeToBuildInfo(string(tspath.ToPath(fileName, t.comparePathsOptions.CurrentDirectory, t.comparePathsOptions.UseCaseSensitiveFileNames))),
+ }
+ })
+}
diff --git a/internal/execute/system.go b/internal/execute/system.go
deleted file mode 100644
index db7a40907b..0000000000
--- a/internal/execute/system.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package execute
-
-import (
- "io"
- "time"
-
- "github.com/microsoft/typescript-go/internal/vfs"
-)
-
-type System interface {
- Writer() io.Writer
- FS() vfs.FS
- DefaultLibraryPath() string
- GetCurrentDirectory() string
- WriteOutputIsTTY() bool
- GetWidthOfTerminal() int
- GetEnvironmentVariable(name string) string
-
- Now() time.Time
- SinceStart() time.Duration
-}
-
-type ExitStatus int
-
-const (
- ExitStatusSuccess ExitStatus = 0
- ExitStatusDiagnosticsPresent_OutputsSkipped ExitStatus = 1
- ExitStatusDiagnosticsPresent_OutputsGenerated ExitStatus = 2
- ExitStatusInvalidProject_OutputsSkipped ExitStatus = 3
- ExitStatusProjectReferenceCycle_OutputsSkipped ExitStatus = 4
- ExitStatusNotImplemented ExitStatus = 5
-)
diff --git a/internal/execute/testfs_test.go b/internal/execute/testfs_test.go
deleted file mode 100644
index 9b49e548dc..0000000000
--- a/internal/execute/testfs_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package execute_test
-
-import (
- "github.com/microsoft/typescript-go/internal/collections"
- "github.com/microsoft/typescript-go/internal/vfs"
-)
-
-type testFs struct {
- vfs.FS
- defaultLibs *collections.SyncSet[string]
- writtenFiles collections.SyncSet[string]
-}
-
-func (f *testFs) removeIgnoreLibPath(path string) {
- if f.defaultLibs != nil && f.defaultLibs.Has(path) {
- f.defaultLibs.Delete(path)
- }
-}
-
-// ReadFile reads the file specified by path and returns the content.
-// If the file fails to be read, ok will be false.
-func (f *testFs) ReadFile(path string) (contents string, ok bool) {
- f.removeIgnoreLibPath(path)
- return f.FS.ReadFile(path)
-}
-
-func (f *testFs) WriteFile(path string, data string, writeByteOrderMark bool) error {
- f.removeIgnoreLibPath(path)
- f.writtenFiles.Add(path)
- return f.FS.WriteFile(path, data, writeByteOrderMark)
-}
-
-// Removes `path` and all its contents. Will return the first error it encounters.
-func (f *testFs) Remove(path string) error {
- f.removeIgnoreLibPath(path)
- return f.FS.Remove(path)
-}
diff --git a/internal/execute/tsc.go b/internal/execute/tsc.go
index 066685a34e..226af2db9d 100644
--- a/internal/execute/tsc.go
+++ b/internal/execute/tsc.go
@@ -3,17 +3,17 @@ package execute
import (
"context"
"fmt"
- "runtime"
"strings"
- "time"
"github.com/microsoft/typescript-go/internal/ast"
"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/diagnostics"
+ "github.com/microsoft/typescript-go/internal/execute/build"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/tsc"
"github.com/microsoft/typescript-go/internal/format"
- "github.com/microsoft/typescript-go/internal/incremental"
"github.com/microsoft/typescript-go/internal/jsonutil"
"github.com/microsoft/typescript-go/internal/parser"
"github.com/microsoft/typescript-go/internal/pprof"
@@ -39,27 +39,12 @@ func applyBulkEdits(text string, edits []core.TextChange) string {
return b.String()
}
-type CommandLineResult struct {
- Status ExitStatus
- IncrementalProgram *incremental.Program
- Watcher *Watcher
-}
-
-type CommandLineTesting interface {
- OnListFilesStart()
- OnListFilesEnd()
- OnStatisticsStart()
- OnStatisticsEnd()
- GetTrace() func(str string)
-}
-
-func CommandLine(sys System, commandLineArgs []string, testing CommandLineTesting) CommandLineResult {
+func CommandLine(sys tsc.System, commandLineArgs []string, testing tsc.CommandLineTesting) tsc.CommandLineResult {
if len(commandLineArgs) > 0 {
// !!! build mode
switch strings.ToLower(commandLineArgs[0]) {
case "-b", "--b", "-build", "--build":
- fmt.Fprintln(sys.Writer(), "Build mode is currently unsupported.")
- return CommandLineResult{Status: ExitStatusNotImplemented}
+ return tscBuildCompilation(sys, tsoptions.ParseBuildCommandLine(commandLineArgs, sys), testing)
// case "-f":
// return fmtMain(sys, commandLineArgs[1], commandLineArgs[1])
}
@@ -68,14 +53,14 @@ func CommandLine(sys System, commandLineArgs []string, testing CommandLineTestin
return tscCompilation(sys, tsoptions.ParseCommandLine(commandLineArgs, sys), testing)
}
-func fmtMain(sys System, input, output string) ExitStatus {
+func fmtMain(sys tsc.System, input, output string) tsc.ExitStatus {
ctx := format.WithFormatCodeSettings(context.Background(), format.GetDefaultFormatCodeSettings("\n"), "\n")
input = string(tspath.ToPath(input, sys.GetCurrentDirectory(), sys.FS().UseCaseSensitiveFileNames()))
output = string(tspath.ToPath(output, sys.GetCurrentDirectory(), sys.FS().UseCaseSensitiveFileNames()))
fileContent, ok := sys.FS().ReadFile(input)
if !ok {
fmt.Fprintln(sys.Writer(), "File not found:", input)
- return ExitStatusNotImplemented
+ return tsc.ExitStatusNotImplemented
}
text := fileContent
pathified := tspath.ToPath(input, sys.GetCurrentDirectory(), true)
@@ -89,21 +74,56 @@ func fmtMain(sys System, input, output string) ExitStatus {
if err := sys.FS().WriteFile(output, newText, false); err != nil {
fmt.Fprintln(sys.Writer(), err.Error())
- return ExitStatusNotImplemented
+ return tsc.ExitStatusNotImplemented
+ }
+ return tsc.ExitStatusSuccess
+}
+
+func tscBuildCompilation(sys tsc.System, buildCommand *tsoptions.ParsedBuildCommandLine, testing tsc.CommandLineTesting) tsc.CommandLineResult {
+ reportDiagnostic := tsc.CreateDiagnosticReporter(sys, sys.Writer(), buildCommand.CompilerOptions)
+
+ // if (buildOptions.locale) {
+ // validateLocaleAndSetLanguage(buildOptions.locale, sys, errors);
+ // }
+
+ if len(buildCommand.Errors) > 0 {
+ for _, err := range buildCommand.Errors {
+ reportDiagnostic(err)
+ }
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsSkipped}
+ }
+
+ if pprofDir := buildCommand.CompilerOptions.PprofDir; pprofDir != "" {
+ // !!! stderr?
+ profileSession := pprof.BeginProfiling(pprofDir, sys.Writer())
+ defer profileSession.Stop()
+ }
+
+ if buildCommand.CompilerOptions.Help.IsTrue() {
+ tsc.PrintVersion(sys)
+ tsc.PrintBuildHelp(sys, tsoptions.BuildOpts)
+ return tsc.CommandLineResult{Status: tsc.ExitStatusSuccess}
}
- return ExitStatusSuccess
+
+ // !!! sheetal watch mode
+ orchestrator := build.NewOrchestrator(build.Options{
+ Sys: sys,
+ Command: buildCommand,
+ Testing: testing,
+ })
+ return orchestrator.Start()
}
-func tscCompilation(sys System, commandLine *tsoptions.ParsedCommandLine, testing CommandLineTesting) CommandLineResult {
+func tscCompilation(sys tsc.System, commandLine *tsoptions.ParsedCommandLine, testing tsc.CommandLineTesting) tsc.CommandLineResult {
configFileName := ""
- reportDiagnostic := createDiagnosticReporter(sys, commandLine.CompilerOptions())
+ reportDiagnostic := tsc.CreateDiagnosticReporter(sys, sys.Writer(), commandLine.CompilerOptions())
// if commandLine.Options().Locale != nil
if len(commandLine.Errors) > 0 {
for _, e := range commandLine.Errors {
reportDiagnostic(e)
}
- return CommandLineResult{Status: ExitStatusDiagnosticsPresent_OutputsSkipped}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsSkipped}
}
if pprofDir := commandLine.CompilerOptions().PprofDir; pprofDir != "" {
@@ -113,28 +133,28 @@ func tscCompilation(sys System, commandLine *tsoptions.ParsedCommandLine, testin
}
if commandLine.CompilerOptions().Init.IsTrue() {
- return CommandLineResult{Status: ExitStatusNotImplemented}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusNotImplemented}
}
if commandLine.CompilerOptions().Version.IsTrue() {
- printVersion(sys)
- return CommandLineResult{Status: ExitStatusSuccess}
+ tsc.PrintVersion(sys)
+ return tsc.CommandLineResult{Status: tsc.ExitStatusSuccess}
}
if commandLine.CompilerOptions().Help.IsTrue() || commandLine.CompilerOptions().All.IsTrue() {
- printHelp(sys, commandLine)
- return CommandLineResult{Status: ExitStatusSuccess}
+ tsc.PrintHelp(sys, commandLine)
+ return tsc.CommandLineResult{Status: tsc.ExitStatusSuccess}
}
if commandLine.CompilerOptions().Watch.IsTrue() && commandLine.CompilerOptions().ListFilesOnly.IsTrue() {
reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Options_0_and_1_cannot_be_combined, "watch", "listFilesOnly"))
- return CommandLineResult{Status: ExitStatusDiagnosticsPresent_OutputsSkipped}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsSkipped}
}
if commandLine.CompilerOptions().Project != "" {
if len(commandLine.FileNames()) != 0 {
reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line))
- return CommandLineResult{Status: ExitStatusDiagnosticsPresent_OutputsSkipped}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsSkipped}
}
fileOrDirectory := tspath.NormalizePath(commandLine.CompilerOptions().Project)
@@ -142,13 +162,13 @@ func tscCompilation(sys System, commandLine *tsoptions.ParsedCommandLine, testin
configFileName = tspath.CombinePaths(fileOrDirectory, "tsconfig.json")
if !sys.FS().FileExists(configFileName) {
reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Cannot_find_a_tsconfig_json_file_at_the_current_directory_Colon_0, configFileName))
- return CommandLineResult{Status: ExitStatusDiagnosticsPresent_OutputsSkipped}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsSkipped}
}
} else {
configFileName = fileOrDirectory
if !sys.FS().FileExists(configFileName) {
reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.The_specified_path_does_not_exist_Colon_0, fileOrDirectory))
- return CommandLineResult{Status: ExitStatusDiagnosticsPresent_OutputsSkipped}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsSkipped}
}
}
} else if len(commandLine.FileNames()) == 0 {
@@ -160,48 +180,50 @@ func tscCompilation(sys System, commandLine *tsoptions.ParsedCommandLine, testin
if commandLine.CompilerOptions().ShowConfig.IsTrue() {
reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Cannot_find_a_tsconfig_json_file_at_the_current_directory_Colon_0, tspath.NormalizePath(sys.GetCurrentDirectory())))
} else {
- printVersion(sys)
- printHelp(sys, commandLine)
+ tsc.PrintVersion(sys)
+ tsc.PrintHelp(sys, commandLine)
}
- return CommandLineResult{Status: ExitStatusDiagnosticsPresent_OutputsSkipped}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsSkipped}
}
// !!! convert to options with absolute paths is usually done here, but for ease of implementation, it's done in `tsoptions.ParseCommandLine()`
compilerOptionsFromCommandLine := commandLine.CompilerOptions()
configForCompilation := commandLine
var extendedConfigCache collections.SyncMap[tspath.Path, *tsoptions.ExtendedConfigCacheEntry]
- var configTime time.Duration
+ var compileTimes tsc.CompileTimes
if configFileName != "" {
configStart := sys.Now()
configParseResult, errors := tsoptions.GetParsedCommandLineOfConfigFile(configFileName, compilerOptionsFromCommandLine, sys, &extendedConfigCache)
- configTime = sys.Now().Sub(configStart)
+ compileTimes.ConfigTime = sys.Now().Sub(configStart)
if len(errors) != 0 {
// these are unrecoverable errors--exit to report them as diagnostics
for _, e := range errors {
reportDiagnostic(e)
}
- return CommandLineResult{Status: ExitStatusDiagnosticsPresent_OutputsGenerated}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusDiagnosticsPresent_OutputsGenerated}
}
configForCompilation = configParseResult
// Updater to reflect pretty
- reportDiagnostic = createDiagnosticReporter(sys, commandLine.CompilerOptions())
+ reportDiagnostic = tsc.CreateDiagnosticReporter(sys, sys.Writer(), commandLine.CompilerOptions())
}
+ reportErrorSummary := tsc.CreateReportErrorSummary(sys, configForCompilation.CompilerOptions())
if compilerOptionsFromCommandLine.ShowConfig.IsTrue() {
showConfig(sys, configForCompilation.CompilerOptions())
- return CommandLineResult{Status: ExitStatusSuccess}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusSuccess}
}
if configForCompilation.CompilerOptions().Watch.IsTrue() {
- watcher := createWatcher(sys, configForCompilation, reportDiagnostic, testing)
+ watcher := createWatcher(sys, configForCompilation, reportDiagnostic, reportErrorSummary, testing)
watcher.start()
- return CommandLineResult{Status: ExitStatusSuccess, Watcher: watcher}
+ return tsc.CommandLineResult{Status: tsc.ExitStatusSuccess, Watcher: watcher}
} else if configForCompilation.CompilerOptions().IsIncremental() {
return performIncrementalCompilation(
sys,
configForCompilation,
reportDiagnostic,
+ reportErrorSummary,
&extendedConfigCache,
- configTime,
+ compileTimes,
testing,
)
}
@@ -209,8 +231,9 @@ func tscCompilation(sys System, commandLine *tsoptions.ParsedCommandLine, testin
sys,
configForCompilation,
reportDiagnostic,
+ reportErrorSummary,
&extendedConfigCache,
- configTime,
+ compileTimes,
testing,
)
}
@@ -229,28 +252,23 @@ func findConfigFile(searchPath string, fileExists func(string) bool, configName
return result
}
-func getTraceFromSys(sys System, testing CommandLineTesting) func(msg string) {
- if testing == nil {
- return func(msg string) {
- fmt.Fprintln(sys.Writer(), msg)
- }
- } else {
- return testing.GetTrace()
- }
+func getTraceFromSys(sys tsc.System, testing tsc.CommandLineTesting) func(msg string) {
+ return tsc.GetTraceWithWriterFromSys(sys.Writer(), testing)
}
func performIncrementalCompilation(
- sys System,
+ sys tsc.System,
config *tsoptions.ParsedCommandLine,
- reportDiagnostic diagnosticReporter,
+ reportDiagnostic tsc.DiagnosticReporter,
+ reportErrorSummary tsc.DiagnosticsReporter,
extendedConfigCache *collections.SyncMap[tspath.Path, *tsoptions.ExtendedConfigCacheEntry],
- configTime time.Duration,
- testing CommandLineTesting,
-) CommandLineResult {
+ compileTimes tsc.CompileTimes,
+ testing tsc.CommandLineTesting,
+) tsc.CommandLineResult {
host := compiler.NewCachedFSCompilerHost(sys.GetCurrentDirectory(), sys.FS(), sys.DefaultLibraryPath(), extendedConfigCache, getTraceFromSys(sys, testing))
buildInfoReadStart := sys.Now()
oldProgram := incremental.ReadBuildInfoProgram(config, incremental.NewBuildInfoReader(host), host)
- buildInfoReadTime := sys.Now().Sub(buildInfoReadStart)
+ compileTimes.BuildInfoReadTime = sys.Now().Sub(buildInfoReadStart)
// todo: cache, statistics, tracing
parseStart := sys.Now()
program := compiler.NewProgram(compiler.ProgramOptions{
@@ -258,36 +276,36 @@ func performIncrementalCompilation(
Host: host,
JSDocParsingMode: ast.JSDocParsingModeParseForTypeErrors,
})
- parseTime := sys.Now().Sub(parseStart)
+ compileTimes.ParseTime = sys.Now().Sub(parseStart)
changesComputeStart := sys.Now()
- incrementalProgram := incremental.NewProgram(program, oldProgram, testing != nil)
- changesComputeTime := sys.Now().Sub(changesComputeStart)
- return CommandLineResult{
- Status: emitAndReportStatistics(
- sys,
- incrementalProgram,
- incrementalProgram.GetProgram(),
- config,
- reportDiagnostic,
- configTime,
- parseTime,
-
- buildInfoReadTime,
- changesComputeTime,
- testing,
- ),
- IncrementalProgram: incrementalProgram,
+ incrementalProgram := incremental.NewProgram(program, oldProgram, nil, testing != nil)
+ compileTimes.ChangesComputeTime = sys.Now().Sub(changesComputeStart)
+ result, _ := tsc.EmitAndReportStatistics(
+ sys,
+ incrementalProgram,
+ incrementalProgram.GetProgram(),
+ config,
+ reportDiagnostic,
+ reportErrorSummary,
+ sys.Writer(),
+ compileTimes,
+ testing,
+ )
+ return tsc.CommandLineResult{
+ Status: result.Status,
+ IncrementalProgram: []*incremental.Program{incrementalProgram},
}
}
func performCompilation(
- sys System,
+ sys tsc.System,
config *tsoptions.ParsedCommandLine,
- reportDiagnostic diagnosticReporter,
+ reportDiagnostic tsc.DiagnosticReporter,
+ reportErrorSummary tsc.DiagnosticsReporter,
extendedConfigCache *collections.SyncMap[tspath.Path, *tsoptions.ExtendedConfigCacheEntry],
- configTime time.Duration,
- testing CommandLineTesting,
-) CommandLineResult {
+ compileTimes tsc.CompileTimes,
+ testing tsc.CommandLineTesting,
+) tsc.CommandLineResult {
host := compiler.NewCachedFSCompilerHost(sys.GetCurrentDirectory(), sys.FS(), sys.DefaultLibraryPath(), extendedConfigCache, getTraceFromSys(sys, testing))
// todo: cache, statistics, tracing
parseStart := sys.Now()
@@ -296,157 +314,24 @@ func performCompilation(
Host: host,
JSDocParsingMode: ast.JSDocParsingModeParseForTypeErrors,
})
- parseTime := sys.Now().Sub(parseStart)
- return CommandLineResult{
- Status: emitAndReportStatistics(
- sys,
- program,
- program,
- config,
- reportDiagnostic,
- configTime,
- parseTime,
- 0,
- 0,
- testing,
- ),
- }
-}
-
-func emitAndReportStatistics(
- sys System,
- programLike compiler.ProgramLike,
- program *compiler.Program,
- config *tsoptions.ParsedCommandLine,
- reportDiagnostic diagnosticReporter,
- configTime time.Duration,
- parseTime time.Duration,
- buildInfoReadTime time.Duration,
- changesComputeTime time.Duration,
- testing CommandLineTesting,
-) ExitStatus {
- result := emitFilesAndReportErrors(sys, programLike, program, reportDiagnostic, testing)
- if result.status != ExitStatusSuccess {
- // compile exited early
- return result.status
- }
-
- result.configTime = configTime
- result.parseTime = parseTime
- result.buildInfoReadTime = buildInfoReadTime
- result.changesComputeTime = changesComputeTime
- result.totalTime = sys.SinceStart()
-
- if config.CompilerOptions().Diagnostics.IsTrue() || config.CompilerOptions().ExtendedDiagnostics.IsTrue() {
- var memStats runtime.MemStats
- // GC must be called twice to allow things to settle.
- runtime.GC()
- runtime.GC()
- runtime.ReadMemStats(&memStats)
-
- reportStatistics(sys, program, result, &memStats, testing)
- }
-
- if result.emitResult.EmitSkipped && len(result.diagnostics) > 0 {
- return ExitStatusDiagnosticsPresent_OutputsSkipped
- } else if len(result.diagnostics) > 0 {
- return ExitStatusDiagnosticsPresent_OutputsGenerated
- }
- return ExitStatusSuccess
-}
-
-type compileAndEmitResult struct {
- diagnostics []*ast.Diagnostic
- emitResult *compiler.EmitResult
- status ExitStatus
- configTime time.Duration
- parseTime time.Duration
- bindTime time.Duration
- checkTime time.Duration
- totalTime time.Duration
- emitTime time.Duration
- buildInfoReadTime time.Duration
- changesComputeTime time.Duration
-}
-
-func emitFilesAndReportErrors(
- sys System,
- programLike compiler.ProgramLike,
- program *compiler.Program,
- reportDiagnostic diagnosticReporter,
- testing CommandLineTesting,
-) (result compileAndEmitResult) {
- ctx := context.Background()
-
- allDiagnostics := compiler.GetDiagnosticsOfAnyProgram(
- ctx,
- programLike,
- nil,
- false,
- func(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic {
- // Options diagnostics include global diagnostics (even though we collect them separately),
- // 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 := 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 := programLike.GetSemanticDiagnostics(ctx, file)
- result.checkTime = sys.Now().Sub(checkStart)
- return diags
- },
+ compileTimes.ParseTime = sys.Now().Sub(parseStart)
+ result, _ := tsc.EmitAndReportStatistics(
+ sys,
+ program,
+ program,
+ config,
+ reportDiagnostic,
+ reportErrorSummary,
+ sys.Writer(),
+ compileTimes,
+ testing,
)
-
- emitResult := &compiler.EmitResult{EmitSkipped: true, Diagnostics: []*ast.Diagnostic{}}
- if !programLike.Options().ListFilesOnly.IsTrue() {
- emitStart := sys.Now()
- emitResult = programLike.Emit(ctx, compiler.EmitOptions{})
- result.emitTime = sys.Now().Sub(emitStart)
- }
- if emitResult != nil {
- allDiagnostics = append(allDiagnostics, emitResult.Diagnostics...)
+ return tsc.CommandLineResult{
+ Status: result.Status,
}
-
- allDiagnostics = compiler.SortAndDeduplicateDiagnostics(allDiagnostics)
- for _, diagnostic := range allDiagnostics {
- reportDiagnostic(diagnostic)
- }
-
- listFiles(sys, program, emitResult, testing)
-
- createReportErrorSummary(sys, programLike.Options())(allDiagnostics)
- result.diagnostics = allDiagnostics
- result.emitResult = emitResult
- result.status = ExitStatusSuccess
- return result
}
-// func isBuildCommand(args []string) bool {
-// return len(args) > 0 && args[0] == "build"
-// }
-
-func showConfig(sys System, config *core.CompilerOptions) {
+func showConfig(sys tsc.System, config *core.CompilerOptions) {
// !!!
_ = jsonutil.MarshalIndentWrite(sys.Writer(), config, "", " ")
}
-
-func listFiles(sys System, program *compiler.Program, emitResult *compiler.EmitResult, testing CommandLineTesting) {
- if testing != nil {
- testing.OnListFilesStart()
- defer testing.OnListFilesEnd()
- }
- for _, file := range emitResult.EmittedFiles {
- fmt.Fprintln(sys.Writer(), "TSFILE: ", tspath.GetNormalizedAbsolutePath(file, sys.GetCurrentDirectory()))
- }
- options := program.Options()
- 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/tsc/compile.go b/internal/execute/tsc/compile.go
new file mode 100644
index 0000000000..cceb0f4c96
--- /dev/null
+++ b/internal/execute/tsc/compile.go
@@ -0,0 +1,75 @@
+package tsc
+
+import (
+ "io"
+ "time"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/compiler"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
+ "github.com/microsoft/typescript-go/internal/vfs"
+)
+
+type System interface {
+ Writer() io.Writer
+ FS() vfs.FS
+ DefaultLibraryPath() string
+ GetCurrentDirectory() string
+ WriteOutputIsTTY() bool
+ GetWidthOfTerminal() int
+ GetEnvironmentVariable(name string) string
+
+ Now() time.Time
+ SinceStart() time.Duration
+}
+
+type ExitStatus int
+
+const (
+ ExitStatusSuccess ExitStatus = 0
+ ExitStatusDiagnosticsPresent_OutputsGenerated ExitStatus = 1
+ ExitStatusDiagnosticsPresent_OutputsSkipped ExitStatus = 2
+ ExitStatusInvalidProject_OutputsSkipped ExitStatus = 3
+ ExitStatusProjectReferenceCycle_OutputsSkipped ExitStatus = 4
+ ExitStatusNotImplemented ExitStatus = 5
+)
+
+type Watcher interface {
+ DoCycle()
+ GetProgram() *incremental.Program
+}
+
+type CommandLineResult struct {
+ Status ExitStatus
+ IncrementalProgram []*incremental.Program
+ Watcher Watcher
+}
+
+type CommandLineTesting interface {
+ // Ensure that all emitted files are timestamped in order to ensure they are deterministic for test baseline
+ OnEmittedFiles(result *compiler.EmitResult)
+ OnListFilesStart(w io.Writer)
+ OnListFilesEnd(w io.Writer)
+ OnStatisticsStart(w io.Writer)
+ OnStatisticsEnd(w io.Writer)
+ OnBuildStatusReportStart(w io.Writer)
+ OnBuildStatusReportEnd(w io.Writer)
+ GetTrace(w io.Writer) func(msg string)
+}
+
+type CompileTimes struct {
+ ConfigTime time.Duration
+ ParseTime time.Duration
+ bindTime time.Duration
+ checkTime time.Duration
+ totalTime time.Duration
+ emitTime time.Duration
+ BuildInfoReadTime time.Duration
+ ChangesComputeTime time.Duration
+}
+type CompileAndEmitResult struct {
+ Diagnostics []*ast.Diagnostic
+ EmitResult *compiler.EmitResult
+ Status ExitStatus
+ times CompileTimes
+}
diff --git a/internal/execute/tsc/diagnostics.go b/internal/execute/tsc/diagnostics.go
new file mode 100644
index 0000000000..cb6154d562
--- /dev/null
+++ b/internal/execute/tsc/diagnostics.go
@@ -0,0 +1,147 @@
+package tsc
+
+import (
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/diagnosticwriter"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+func getFormatOptsOfSys(sys System) *diagnosticwriter.FormattingOptions {
+ return &diagnosticwriter.FormattingOptions{
+ NewLine: "\n",
+ ComparePathsOptions: tspath.ComparePathsOptions{
+ CurrentDirectory: sys.GetCurrentDirectory(),
+ UseCaseSensitiveFileNames: sys.FS().UseCaseSensitiveFileNames(),
+ },
+ }
+}
+
+type DiagnosticReporter = func(*ast.Diagnostic)
+
+func QuietDiagnosticReporter(diagnostic *ast.Diagnostic) {}
+func CreateDiagnosticReporter(sys System, w io.Writer, options *core.CompilerOptions) DiagnosticReporter {
+ if options.Quiet.IsTrue() {
+ return QuietDiagnosticReporter
+ }
+
+ formatOpts := getFormatOptsOfSys(sys)
+ writeDiagnostic := core.IfElse(shouldBePretty(sys, options), diagnosticwriter.FormatDiagnosticWithColorAndContext, diagnosticwriter.WriteFormatDiagnostic)
+ return func(diagnostic *ast.Diagnostic) {
+ writeDiagnostic(w, diagnostic, formatOpts)
+ fmt.Fprint(w, formatOpts.NewLine)
+ }
+}
+
+func defaultIsPretty(sys System) bool {
+ return sys.WriteOutputIsTTY() && sys.GetEnvironmentVariable("NO_COLOR") == ""
+}
+
+func shouldBePretty(sys System, options *core.CompilerOptions) bool {
+ if options == nil || options.Pretty.IsUnknown() {
+ return defaultIsPretty(sys)
+ }
+ return options.Pretty.IsTrue()
+}
+
+type colors struct {
+ showColors bool
+
+ isWindows bool
+ isWindowsTerminal bool
+ isVSCode bool
+ supportsRicherColors bool
+}
+
+func createColors(sys System) *colors {
+ if !defaultIsPretty(sys) {
+ return &colors{showColors: false}
+ }
+
+ os := sys.GetEnvironmentVariable("OS")
+ isWindows := strings.Contains(strings.ToLower(os), "windows")
+ isWindowsTerminal := sys.GetEnvironmentVariable("WT_SESSION") != ""
+ isVSCode := sys.GetEnvironmentVariable("TERM_PROGRAM") == "vscode"
+ supportsRicherColors := sys.GetEnvironmentVariable("COLORTERM") == "truecolor" || sys.GetEnvironmentVariable("TERM") == "xterm-256color"
+
+ return &colors{
+ showColors: true,
+ isWindows: isWindows,
+ isWindowsTerminal: isWindowsTerminal,
+ isVSCode: isVSCode,
+ supportsRicherColors: supportsRicherColors,
+ }
+}
+
+func (c *colors) bold(str string) string {
+ if !c.showColors {
+ return str
+ }
+ return "\x1b[1m" + str + "\x1b[22m"
+}
+
+func (c *colors) blue(str string) string {
+ if !c.showColors {
+ return str
+ }
+
+ // Effectively Powershell and Command prompt users use cyan instead
+ // of blue because the default theme doesn't show blue with enough contrast.
+ if c.isWindows && !c.isWindowsTerminal && !c.isVSCode {
+ return c.brightWhite(str)
+ }
+ return "\x1b[94m" + str + "\x1b[39m"
+}
+
+func (c *colors) blueBackground(str string) string {
+ if !c.showColors {
+ return str
+ }
+ if c.supportsRicherColors {
+ return "\x1B[48;5;68m" + str + "\x1B[39;49m"
+ } else {
+ return "\x1b[44m" + str + "\x1B[39;49m"
+ }
+}
+
+func (c *colors) brightWhite(str string) string {
+ if !c.showColors {
+ return str
+ }
+ return "\x1b[97m" + str + "\x1b[39m"
+}
+
+type DiagnosticsReporter = func(diagnostics []*ast.Diagnostic)
+
+func QuietDiagnosticsReporter(diagnostics []*ast.Diagnostic) {}
+
+func CreateReportErrorSummary(sys System, options *core.CompilerOptions) DiagnosticsReporter {
+ if shouldBePretty(sys, options) {
+ formatOpts := getFormatOptsOfSys(sys)
+ return func(diagnostics []*ast.Diagnostic) {
+ diagnosticwriter.WriteErrorSummaryText(sys.Writer(), diagnostics, formatOpts)
+ }
+ }
+ return QuietDiagnosticsReporter
+}
+
+func CreateBuilderStatusReporter(sys System, w io.Writer, options *core.CompilerOptions, testing CommandLineTesting) DiagnosticReporter {
+ if options.Quiet.IsTrue() {
+ return QuietDiagnosticReporter
+ }
+
+ formatOpts := getFormatOptsOfSys(sys)
+ writeStatus := core.IfElse(shouldBePretty(sys, options), diagnosticwriter.FormatDiagnosticsStatusWithColorAndTime, diagnosticwriter.FormatDiagnosticsStatusAndTime)
+ return func(diagnostic *ast.Diagnostic) {
+ if testing != nil {
+ testing.OnBuildStatusReportStart(w)
+ defer testing.OnBuildStatusReportEnd(w)
+ }
+ writeStatus(w, sys.Now().Format("03:04:05 PM"), diagnostic, formatOpts)
+ fmt.Fprint(w, formatOpts.NewLine, formatOpts.NewLine)
+ }
+}
diff --git a/internal/execute/tsc/emit.go b/internal/execute/tsc/emit.go
new file mode 100644
index 0000000000..499fff29da
--- /dev/null
+++ b/internal/execute/tsc/emit.go
@@ -0,0 +1,143 @@
+package tsc
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "runtime"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/compiler"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+func GetTraceWithWriterFromSys(w io.Writer, testing CommandLineTesting) func(msg string) {
+ if testing == nil {
+ return func(msg string) {
+ fmt.Fprintln(w, msg)
+ }
+ } else {
+ return testing.GetTrace(w)
+ }
+}
+
+func EmitAndReportStatistics(
+ sys System,
+ programLike compiler.ProgramLike,
+ program *compiler.Program,
+ config *tsoptions.ParsedCommandLine,
+ reportDiagnostic DiagnosticReporter,
+ reportErrorSummary DiagnosticsReporter,
+ w io.Writer,
+ compileTimes CompileTimes,
+ testing CommandLineTesting,
+) (CompileAndEmitResult, *Statistics) {
+ var statistics *Statistics
+ result := EmitFilesAndReportErrors(sys, programLike, program, reportDiagnostic, reportErrorSummary, w, compileTimes, testing)
+ if result.Status != ExitStatusSuccess {
+ // compile exited early
+ return result, nil
+ }
+ result.times.totalTime = sys.SinceStart()
+
+ if config.CompilerOptions().Diagnostics.IsTrue() || config.CompilerOptions().ExtendedDiagnostics.IsTrue() {
+ var memStats runtime.MemStats
+ // GC must be called twice to allow things to settle.
+ runtime.GC()
+ runtime.GC()
+ runtime.ReadMemStats(&memStats)
+
+ statistics = statisticsFromProgram(program, &compileTimes, &memStats)
+ statistics.Report(w, testing)
+ }
+
+ if result.EmitResult.EmitSkipped && len(result.Diagnostics) > 0 {
+ result.Status = ExitStatusDiagnosticsPresent_OutputsSkipped
+ } else if len(result.Diagnostics) > 0 {
+ result.Status = ExitStatusDiagnosticsPresent_OutputsGenerated
+ }
+ return result, statistics
+}
+
+func EmitFilesAndReportErrors(
+ sys System,
+ programLike compiler.ProgramLike,
+ program *compiler.Program,
+ reportDiagnostic DiagnosticReporter,
+ reportErrorSummary DiagnosticsReporter,
+ w io.Writer,
+ compileTimes CompileTimes,
+ testing CommandLineTesting,
+) (result CompileAndEmitResult) {
+ result.times = compileTimes
+ ctx := context.Background()
+
+ allDiagnostics := compiler.GetDiagnosticsOfAnyProgram(
+ ctx,
+ programLike,
+ nil,
+ false,
+ func(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic {
+ // Options diagnostics include global diagnostics (even though we collect them separately),
+ // 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 := programLike.GetBindDiagnostics(ctx, file)
+ result.times.bindTime = sys.Now().Sub(bindStart)
+ return diags
+ },
+ func(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic {
+ checkStart := sys.Now()
+ diags := programLike.GetSemanticDiagnostics(ctx, file)
+ result.times.checkTime = sys.Now().Sub(checkStart)
+ return diags
+ },
+ )
+
+ emitResult := &compiler.EmitResult{EmitSkipped: true, Diagnostics: []*ast.Diagnostic{}}
+ if !programLike.Options().ListFilesOnly.IsTrue() {
+ emitStart := sys.Now()
+ emitResult = programLike.Emit(ctx, compiler.EmitOptions{})
+ result.times.emitTime = sys.Now().Sub(emitStart)
+ }
+ if emitResult != nil {
+ allDiagnostics = append(allDiagnostics, emitResult.Diagnostics...)
+ }
+ if testing != nil {
+ testing.OnEmittedFiles(emitResult)
+ }
+
+ allDiagnostics = compiler.SortAndDeduplicateDiagnostics(allDiagnostics)
+ for _, diagnostic := range allDiagnostics {
+ reportDiagnostic(diagnostic)
+ }
+
+ listFiles(w, program, emitResult, testing)
+
+ reportErrorSummary(allDiagnostics)
+ result.Diagnostics = allDiagnostics
+ result.EmitResult = emitResult
+ result.Status = ExitStatusSuccess
+ return result
+}
+
+func listFiles(w io.Writer, program *compiler.Program, emitResult *compiler.EmitResult, testing CommandLineTesting) {
+ if testing != nil {
+ testing.OnListFilesStart(w)
+ defer testing.OnListFilesEnd(w)
+ }
+ options := program.Options()
+ if options.ListEmittedFiles.IsTrue() {
+ for _, file := range emitResult.EmittedFiles {
+ fmt.Fprintln(w, "TSFILE: ", tspath.GetNormalizedAbsolutePath(file, program.GetCurrentDirectory()))
+ }
+ }
+ if options.ExplainFiles.IsTrue() {
+ program.ExplainFiles(w)
+ } else if options.ListFiles.IsTrue() || options.ListFilesOnly.IsTrue() {
+ for _, file := range program.GetSourceFiles() {
+ fmt.Fprintln(w, file.FileName())
+ }
+ }
+}
diff --git a/internal/execute/outputs.go b/internal/execute/tsc/help.go
similarity index 69%
rename from internal/execute/outputs.go
rename to internal/execute/tsc/help.go
index 29b1e4c825..f3467a6b6d 100644
--- a/internal/execute/outputs.go
+++ b/internal/execute/tsc/help.go
@@ -1,183 +1,21 @@
-package execute
+package tsc
import (
"fmt"
- "io"
- "runtime"
"slices"
- "strconv"
"strings"
- "time"
- "github.com/microsoft/typescript-go/internal/ast"
"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/diagnostics"
- "github.com/microsoft/typescript-go/internal/diagnosticwriter"
"github.com/microsoft/typescript-go/internal/tsoptions"
- "github.com/microsoft/typescript-go/internal/tspath"
)
-func getFormatOptsOfSys(sys System) *diagnosticwriter.FormattingOptions {
- return &diagnosticwriter.FormattingOptions{
- NewLine: "\n",
- ComparePathsOptions: tspath.ComparePathsOptions{
- CurrentDirectory: sys.GetCurrentDirectory(),
- UseCaseSensitiveFileNames: sys.FS().UseCaseSensitiveFileNames(),
- },
- }
-}
-
-type diagnosticReporter = func(*ast.Diagnostic)
-
-func quietDiagnosticReporter(diagnostic *ast.Diagnostic) {}
-func createDiagnosticReporter(sys System, options *core.CompilerOptions) diagnosticReporter {
- if options.Quiet.IsTrue() {
- return quietDiagnosticReporter
- }
-
- formatOpts := getFormatOptsOfSys(sys)
- writeDiagnostic := core.IfElse(shouldBePretty(sys, options), diagnosticwriter.FormatDiagnosticWithColorAndContext, diagnosticwriter.WriteFormatDiagnostic)
-
- return func(diagnostic *ast.Diagnostic) {
- writeDiagnostic(sys.Writer(), diagnostic, formatOpts)
- fmt.Fprint(sys.Writer(), formatOpts.NewLine)
- }
-}
-
-func defaultIsPretty(sys System) bool {
- return sys.WriteOutputIsTTY() && sys.GetEnvironmentVariable("NO_COLOR") == ""
-}
-
-func shouldBePretty(sys System, options *core.CompilerOptions) bool {
- if options == nil || options.Pretty.IsUnknown() {
- return defaultIsPretty(sys)
- }
- return options.Pretty.IsTrue()
-}
-
-type colors struct {
- showColors bool
-
- isWindows bool
- isWindowsTerminal bool
- isVSCode bool
- supportsRicherColors bool
-}
-
-func createColors(sys System) *colors {
- if !defaultIsPretty(sys) {
- return &colors{showColors: false}
- }
-
- os := sys.GetEnvironmentVariable("OS")
- isWindows := strings.Contains(strings.ToLower(os), "windows")
- isWindowsTerminal := sys.GetEnvironmentVariable("WT_SESSION") != ""
- isVSCode := sys.GetEnvironmentVariable("TERM_PROGRAM") == "vscode"
- supportsRicherColors := sys.GetEnvironmentVariable("COLORTERM") == "truecolor" || sys.GetEnvironmentVariable("TERM") == "xterm-256color"
-
- return &colors{
- showColors: true,
- isWindows: isWindows,
- isWindowsTerminal: isWindowsTerminal,
- isVSCode: isVSCode,
- supportsRicherColors: supportsRicherColors,
- }
-}
-
-func (c *colors) bold(str string) string {
- if !c.showColors {
- return str
- }
- return "\x1b[1m" + str + "\x1b[22m"
-}
-
-func (c *colors) blue(str string) string {
- if !c.showColors {
- return str
- }
-
- // Effectively Powershell and Command prompt users use cyan instead
- // of blue because the default theme doesn't show blue with enough contrast.
- if c.isWindows && !c.isWindowsTerminal && !c.isVSCode {
- return c.brightWhite(str)
- }
- return "\x1b[94m" + str + "\x1b[39m"
-}
-
-func (c *colors) blueBackground(str string) string {
- if !c.showColors {
- return str
- }
- if c.supportsRicherColors {
- return "\x1B[48;5;68m" + str + "\x1B[39;49m"
- } else {
- return "\x1b[44m" + str + "\x1B[39;49m"
- }
-}
-
-func (c *colors) brightWhite(str string) string {
- if !c.showColors {
- return str
- }
- return "\x1b[97m" + str + "\x1b[39m"
-}
-
-func createReportErrorSummary(sys System, options *core.CompilerOptions) func(diagnostics []*ast.Diagnostic) {
- if shouldBePretty(sys, options) {
- formatOpts := getFormatOptsOfSys(sys)
- return func(diagnostics []*ast.Diagnostic) {
- diagnosticwriter.WriteErrorSummaryText(sys.Writer(), diagnostics, formatOpts)
- }
- }
- return func(diagnostics []*ast.Diagnostic) {}
-}
-
-func reportStatistics(sys System, program *compiler.Program, result compileAndEmitResult, memStats *runtime.MemStats, testing CommandLineTesting) {
- var stats table
-
- if testing != nil {
- testing.OnStatisticsStart()
- defer testing.OnStatisticsEnd()
- }
- stats.add("Files", len(program.SourceFiles()))
- stats.add("Lines", program.LineCount())
- stats.add("Identifiers", program.IdentifierCount())
- stats.add("Symbols", program.SymbolCount())
- stats.add("Types", program.TypeCount())
- stats.add("Instantiations", program.InstantiationCount())
- stats.add("Memory used", fmt.Sprintf("%vK", memStats.Alloc/1024))
- stats.add("Memory allocs", strconv.FormatUint(memStats.Mallocs, 10))
- if result.configTime != 0 {
- stats.add("Config time", result.configTime)
- }
- if result.buildInfoReadTime != 0 {
- stats.add("BuildInfo read time", result.buildInfoReadTime)
- }
- stats.add("Parse time", result.parseTime)
- if result.bindTime != 0 {
- stats.add("Bind time", result.bindTime)
- }
- if result.checkTime != 0 {
- stats.add("Check time", result.checkTime)
- }
- if result.emitTime != 0 {
- stats.add("Emit time", result.emitTime)
- }
- if result.changesComputeTime != 0 {
- stats.add("Changes compute time", result.changesComputeTime)
- }
- stats.add("Total time", result.totalTime)
-
- stats.print(sys.Writer())
-}
-
-func printVersion(sys System) {
+func PrintVersion(sys System) {
fmt.Fprintln(sys.Writer(), diagnostics.Version_0.Format(core.Version()))
}
-func printHelp(sys System, commandLine *tsoptions.ParsedCommandLine) {
+func PrintHelp(sys System, commandLine *tsoptions.ParsedCommandLine) {
if commandLine.CompilerOptions().All.IsFalseOrUnknown() {
printEasyHelp(sys, getOptionsForHelp(commandLine))
} else {
@@ -269,6 +107,20 @@ func printEasyHelp(sys System, simpleOptions []*tsoptions.CommandLineOption) {
}
}
+func PrintBuildHelp(sys System, buildOptions []*tsoptions.CommandLineOption) {
+ var output []string
+ output = append(output, getHeader(sys, diagnostics.X_tsc_Colon_The_TypeScript_Compiler.Format()+" - "+diagnostics.Version_0.Format(core.Version()))...)
+ before := diagnostics.Using_build_b_will_make_tsc_behave_more_like_a_build_orchestrator_than_a_compiler_This_is_used_to_trigger_building_composite_projects_which_you_can_learn_more_about_at_0.Format("https://aka.ms/tsc-composite-builds")
+ options := core.Filter(buildOptions, func(option *tsoptions.CommandLineOption) bool {
+ return option != &tsoptions.TscBuildOption
+ })
+ output = append(output, generateSectionOptionsOutput(sys, diagnostics.BUILD_OPTIONS.Format(), options, false, &before, nil)...)
+
+ for _, chunk := range output {
+ fmt.Fprint(sys.Writer(), chunk)
+ }
+}
+
func generateSectionOptionsOutput(
sys System,
sectionName string,
@@ -540,44 +392,3 @@ func getPrettyOutput(colors *colors, left string, right string, rightAlignOfLeft
func getDisplayNameTextOfOption(option *tsoptions.CommandLineOption) string {
return "--" + option.Name + core.IfElse(option.ShortName != "", ", -"+option.ShortName, "")
}
-
-type tableRow struct {
- name string
- value string
-}
-
-type table struct {
- rows []tableRow
-}
-
-func (t *table) add(name string, value any) {
- if d, ok := value.(time.Duration); ok {
- value = formatDuration(d)
- }
- t.rows = append(t.rows, tableRow{name, fmt.Sprint(value)})
-}
-
-func (t *table) print(w io.Writer) {
- nameWidth := 0
- valueWidth := 0
- for _, r := range t.rows {
- nameWidth = max(nameWidth, len(r.name))
- valueWidth = max(valueWidth, len(r.value))
- }
-
- for _, r := range t.rows {
- fmt.Fprintf(w, "%-*s %*s\n", nameWidth+1, r.name+":", valueWidth, r.value)
- }
-}
-
-func formatDuration(d time.Duration) string {
- return fmt.Sprintf("%.3fs", d.Seconds())
-}
-
-func identifierCount(p *compiler.Program) int {
- count := 0
- for _, file := range p.SourceFiles() {
- count += file.IdentifierCount
- }
- return count
-}
diff --git a/internal/execute/tsc/statistics.go b/internal/execute/tsc/statistics.go
new file mode 100644
index 0000000000..fe2e548fa1
--- /dev/null
+++ b/internal/execute/tsc/statistics.go
@@ -0,0 +1,151 @@
+package tsc
+
+import (
+ "fmt"
+ "io"
+ "runtime"
+ "strconv"
+ "time"
+
+ "github.com/microsoft/typescript-go/internal/compiler"
+)
+
+type tableRow struct {
+ name string
+ value string
+}
+
+type table struct {
+ rows []tableRow
+}
+
+func (t *table) add(name string, value any) {
+ if d, ok := value.(time.Duration); ok {
+ value = formatDuration(d)
+ }
+ t.rows = append(t.rows, tableRow{name, fmt.Sprint(value)})
+}
+
+func (t *table) print(w io.Writer) {
+ nameWidth := 0
+ valueWidth := 0
+ for _, r := range t.rows {
+ nameWidth = max(nameWidth, len(r.name))
+ valueWidth = max(valueWidth, len(r.value))
+ }
+
+ for _, r := range t.rows {
+ fmt.Fprintf(w, "%-*s %*s\n", nameWidth+1, r.name+":", valueWidth, r.value)
+ }
+}
+
+func formatDuration(d time.Duration) string {
+ return fmt.Sprintf("%.3fs", d.Seconds())
+}
+
+func identifierCount(p *compiler.Program) int {
+ count := 0
+ for _, file := range p.SourceFiles() {
+ count += file.IdentifierCount
+ }
+ return count
+}
+
+type Statistics struct {
+ isAggregate bool
+ Projects int
+ ProjectsBuilt int
+ TimestampUpdates int
+ files int
+ lines int
+ identifiers int
+ symbols int
+ types int
+ instantiations int
+ memoryUsed uint64
+ memoryAllocs uint64
+ compileTimes *CompileTimes
+}
+
+func statisticsFromProgram(program *compiler.Program, compileTimes *CompileTimes, memStats *runtime.MemStats) *Statistics {
+ return &Statistics{
+ files: len(program.SourceFiles()),
+ lines: program.LineCount(),
+ identifiers: program.IdentifierCount(),
+ symbols: program.SymbolCount(),
+ types: program.TypeCount(),
+ instantiations: program.InstantiationCount(),
+ memoryUsed: memStats.Alloc,
+ memoryAllocs: memStats.Mallocs,
+ compileTimes: compileTimes,
+ }
+}
+
+func (s *Statistics) Report(w io.Writer, testing CommandLineTesting) {
+ if testing != nil {
+ testing.OnStatisticsStart(w)
+ defer testing.OnStatisticsEnd(w)
+ }
+ var table table
+ var prefix string
+
+ if s.isAggregate {
+ prefix = "Aggregate "
+ table.add("Projects in scope", s.Projects)
+ table.add("Projects built", s.ProjectsBuilt)
+ table.add("Timestamps only updates", s.TimestampUpdates)
+ }
+ table.add(prefix+"Files", s.files)
+ table.add(prefix+"Lines", s.lines)
+ table.add(prefix+"Identifiers", s.identifiers)
+ table.add(prefix+"Symbols", s.symbols)
+ table.add(prefix+"Types", s.types)
+ table.add(prefix+"Instantiations", s.instantiations)
+ table.add(prefix+"Memory used", fmt.Sprintf("%vK", s.memoryUsed/1024))
+ table.add(prefix+"Memory allocs", strconv.FormatUint(s.memoryAllocs, 10))
+ if s.compileTimes.ConfigTime != 0 {
+ table.add(prefix+"Config time", s.compileTimes.ConfigTime)
+ }
+ if s.compileTimes.BuildInfoReadTime != 0 {
+ table.add(prefix+"BuildInfo read time", s.compileTimes.BuildInfoReadTime)
+ }
+ table.add(prefix+"Parse time", s.compileTimes.ParseTime)
+ if s.compileTimes.bindTime != 0 {
+ table.add(prefix+"Bind time", s.compileTimes.bindTime)
+ }
+ if s.compileTimes.checkTime != 0 {
+ table.add(prefix+"Check time", s.compileTimes.checkTime)
+ }
+ if s.compileTimes.emitTime != 0 {
+ table.add(prefix+"Emit time", s.compileTimes.emitTime)
+ }
+ if s.compileTimes.ChangesComputeTime != 0 {
+ table.add(prefix+"Changes compute time", s.compileTimes.ChangesComputeTime)
+ }
+ table.add(prefix+"Total time", s.compileTimes.totalTime)
+ table.print(w)
+}
+
+func (s *Statistics) Aggregate(stats []*Statistics, totalTime time.Duration) {
+ s.isAggregate = true
+ s.compileTimes = &CompileTimes{}
+ for _, stat := range stats {
+ // Aggregate statistics
+ s.files += stat.files
+ s.lines += stat.lines
+ s.identifiers += stat.identifiers
+ s.symbols += stat.symbols
+ s.types += stat.types
+ s.instantiations += stat.instantiations
+ s.memoryUsed += stat.memoryUsed
+ s.memoryAllocs += stat.memoryAllocs
+ s.compileTimes.ConfigTime += stat.compileTimes.ConfigTime
+ s.compileTimes.BuildInfoReadTime += stat.compileTimes.BuildInfoReadTime
+ s.compileTimes.ParseTime += stat.compileTimes.ParseTime
+ s.compileTimes.bindTime += stat.compileTimes.bindTime
+ s.compileTimes.checkTime += stat.compileTimes.checkTime
+ s.compileTimes.emitTime += stat.compileTimes.emitTime
+ s.compileTimes.ChangesComputeTime += stat.compileTimes.ChangesComputeTime
+ }
+ s.compileTimes.totalTime = totalTime
+}
diff --git a/internal/execute/tsc_test.go b/internal/execute/tsc_test.go
deleted file mode 100644
index 85ad87e4af..0000000000
--- a/internal/execute/tsc_test.go
+++ /dev/null
@@ -1,268 +0,0 @@
-package execute_test
-
-import (
- "testing"
-
- "github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
-)
-
-func TestTscCommandline(t *testing.T) {
- t.Parallel()
- testCases := []*tscInput{
- {
- subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped",
- env: map[string]string{
- "TS_TEST_TERMINAL_WIDTH": "120",
- },
- commandLineArgs: nil,
- },
- {
- subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped when host cannot provide terminal width",
- commandLineArgs: nil,
- },
- {
- subScenario: "does not add color when NO_COLOR is set",
- env: map[string]string{
- "NO_COLOR": "true",
- },
- commandLineArgs: nil,
- },
- {
- subScenario: "when build not first argument",
- commandLineArgs: []string{"--verbose", "--build"},
- },
- {
- subScenario: "help",
- commandLineArgs: []string{"--help"},
- },
- {
- subScenario: "help all",
- commandLineArgs: []string{"--help", "--all"},
- },
- {
- subScenario: "Parse --lib option with file name",
- files: FileMap{"/home/src/workspaces/project/first.ts": `export const Key = Symbol()`},
- commandLineArgs: []string{"--lib", "es6 ", "first.ts"},
- },
- {
- subScenario: "Project is empty string",
- files: FileMap{
- "/home/src/workspaces/project/first.ts": `export const a = 1`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "strict": true,
- "noEmit": true
- }
- }`),
- },
- commandLineArgs: []string{},
- },
- {
- subScenario: "Parse -p",
- files: FileMap{
- "/home/src/workspaces/project/first.ts": `export const a = 1`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "strict": true,
- "noEmit": true
- }
- }`),
- },
- commandLineArgs: []string{"-p", "."},
- },
- {
- subScenario: "Parse -p with path to tsconfig file",
- files: FileMap{
- "/home/src/workspaces/project/first.ts": `export const a = 1`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "strict": true,
- "noEmit": true
- }
- }`),
- },
- commandLineArgs: []string{"-p", "/home/src/workspaces/project/tsconfig.json"},
- },
- {
- subScenario: "Parse -p with path to tsconfig folder",
- files: FileMap{
- "/home/src/workspaces/project/first.ts": `export const a = 1`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "strict": true,
- "noEmit": true
- }
- }`),
- },
- commandLineArgs: []string{"-p", "/home/src/workspaces/project"},
- },
- {
- subScenario: "Parse enum type options",
- commandLineArgs: []string{"--moduleResolution", "nodenext ", "first.ts", "--module", "nodenext", "--target", "esnext", "--moduleDetection", "auto", "--jsx", "react", "--newLine", "crlf"},
- },
- {
- subScenario: "Parse watch interval option",
- files: FileMap{
- "/home/src/workspaces/project/first.ts": `export const a = 1`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "strict": true,
- "noEmit": true
- }
- }`),
- },
- commandLineArgs: []string{"-w", "--watchInterval", "1000"},
- },
- {
- subScenario: "Parse watch interval option without tsconfig.json",
- commandLineArgs: []string{"-w", "--watchInterval", "1000"},
- },
- {
- subScenario: "Config with references and empty file and refers to config with noEmit",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`{
- "files": [],
- "references": [
- {
- "path": "./packages/pkg1"
- },
- ],
- }`),
- "/home/src/workspaces/project/packages/pkg1/tsconfig.json": stringtestutil.Dedent(`{
- "compilerOptions": {
- "composite": true,
- "noEmit": true
- },
- "files": [
- "./index.ts",
- ],
- }`),
- "/home/src/workspaces/project/packages/pkg1/index.ts": `export const a = 1;`,
- },
- commandLineArgs: []string{"-p", "."},
- },
- }
-
- for _, testCase := range testCases {
- testCase.run(t, "commandLine")
- }
-}
-
-func TestNoEmit(t *testing.T) {
- t.Parallel()
- (&tscInput{
- subScenario: "when project has strict true",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "incremental": true,
- "strict": true
- }
- }`),
- "/home/src/workspaces/project/class1.ts": `export class class1 {}`,
- },
- commandLineArgs: []string{"--noEmit"},
- }).run(t, "noEmit")
-}
-
-func TestExtends(t *testing.T) {
- t.Parallel()
- extendsSysScenario := func(subScenario string, commandlineArgs []string) *tscInput {
- return &tscInput{
- subScenario: subScenario,
- commandLineArgs: commandlineArgs,
- files: FileMap{
- "/home/src/projects/configs/first/tsconfig.json": stringtestutil.Dedent(`
- {
- "extends": "../second/tsconfig.json",
- "include": ["${configDir}/src"],
- "compilerOptions": {
- "typeRoots": ["root1", "${configDir}/root2", "root3"],
- "types": [],
- }
- }`),
- "/home/src/projects/configs/second/tsconfig.json": stringtestutil.Dedent(`
- {
- "files": ["${configDir}/main.ts"],
- "compilerOptions": {
- "declarationDir": "${configDir}/decls",
- "paths": {
- "@myscope/*": ["${configDir}/types/*"],
- "other/*": ["other/*"],
- },
- "baseUrl": "${configDir}",
- },
- "watchOptions": {
- "excludeFiles": ["${configDir}/main.ts"],
- },
- }`),
- "/home/src/projects/myproject/tsconfig.json": stringtestutil.Dedent(`
- {
- "extends": "../configs/first/tsconfig.json",
- "compilerOptions": {
- "declaration": true,
- "outDir": "outDir",
- "traceResolution": true,
- },
- }`),
- "/home/src/projects/myproject/main.ts": stringtestutil.Dedent(`
- // some comment
- export const y = 10;
- import { x } from "@myscope/sometype";
- `),
- "/home/src/projects/myproject/src/secondary.ts": stringtestutil.Dedent(`
- // some comment
- export const z = 10;
- import { k } from "other/sometype2";
- `),
- "/home/src/projects/myproject/types/sometype.ts": stringtestutil.Dedent(`
- // some comment
- export const x = 10;
- `),
- "/home/src/projects/myproject/root2/other/sometype2/index.d.ts": stringtestutil.Dedent(`
- export const k = 10;
- `),
- },
- cwd: "/home/src/projects/myproject",
- }
- }
-
- cases := []*tscInput{
- extendsSysScenario("configDir template", []string{"--explainFiles"}),
- extendsSysScenario("configDir template showConfig", []string{"--showConfig"}),
- extendsSysScenario("configDir template with commandline", []string{"--explainFiles", "--outDir", "${configDir}/outDir"}),
- }
-
- for _, c := range cases {
- c.run(t, "extends")
- }
-}
-
-func TestTypeAcquisition(t *testing.T) {
- t.Parallel()
- (&tscInput{
- subScenario: "parse tsconfig with typeAcquisition",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "noEmit": true,
- },
- "typeAcquisition": {
- "enable": true,
- "include": ["0.d.ts", "1.d.ts"],
- "exclude": ["0.js", "1.js"],
- "disableFilenameBasedTypeAcquisition": true,
- },
- }`),
- },
- commandLineArgs: []string{},
- }).run(t, "typeAcquisition")
-}
diff --git a/internal/execute/tscincremental_test.go b/internal/execute/tscincremental_test.go
deleted file mode 100644
index 76fe263bbc..0000000000
--- a/internal/execute/tscincremental_test.go
+++ /dev/null
@@ -1,701 +0,0 @@
-package execute_test
-
-import (
- "testing"
-
- "github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
-)
-
-func TestIncremental(t *testing.T) {
- t.Parallel()
- testCases := []*tscInput{
- {
- subScenario: "serializing error chain",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "incremental": true,
- "strict": true,
- "jsx": "react",
- "module": "esnext",
- },
- }`),
- "/home/src/workspaces/project/index.tsx": stringtestutil.Dedent(`
- declare namespace JSX {
- interface ElementChildrenAttribute { children: {}; }
- interface IntrinsicElements { div: {} }
- }
-
- declare var React: any;
-
- declare function Component(props: never): any;
- declare function Component(props: { children?: number }): any;
- (
-
-
- )`),
- },
- edits: noChangeOnlyEdit,
- },
- {
- subScenario: "serializing composite project",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "strict": true,
- "module": "esnext",
- },
- }`),
- "/home/src/workspaces/project/index.tsx": `export const a = 1;`,
- "/home/src/workspaces/project/other.ts": `export const b = 2;`,
- },
- },
- {
- subScenario: "change to modifier of class expression field with declaration emit enabled",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "esnext",
- "declaration": true
- }
- }`),
- "/home/src/workspaces/project/main.ts": stringtestutil.Dedent(`
- import MessageablePerson from './MessageablePerson.js';
- function logMessage( person: MessageablePerson ) {
- console.log( person.message );
- }`),
- "/home/src/workspaces/project/MessageablePerson.ts": stringtestutil.Dedent(`
- const Messageable = () => {
- return class MessageableClass {
- public message = 'hello';
- }
- };
- const wrapper = () => Messageable();
- type MessageablePerson = InstanceType>;
- export default MessageablePerson;`),
- tscLibPath + "/lib.d.ts": tscDefaultLibContent + "\n" + stringtestutil.Dedent(`
- type ReturnType any> = T extends (...args: any) => infer R ? R : any;
- type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;`),
- },
- commandLineArgs: []string{"--incremental"},
- edits: []*tscEdit{
- noChange,
- {
- caption: "modify public to protected",
- edit: func(sys *testSys) {
- sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "public", "protected")
- },
- },
- noChange,
- {
- caption: "modify protected to public",
- edit: func(sys *testSys) {
- sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "protected", "public")
- },
- },
- noChange,
- },
- },
- {
- subScenario: "change to modifier of class expression field",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "esnext"
- }
- }`),
- "/home/src/workspaces/project/main.ts": stringtestutil.Dedent(`
- import MessageablePerson from './MessageablePerson.js';
- function logMessage( person: MessageablePerson ) {
- console.log( person.message );
- }`),
- "/home/src/workspaces/project/MessageablePerson.ts": stringtestutil.Dedent(`
- const Messageable = () => {
- return class MessageableClass {
- public message = 'hello';
- }
- };
- const wrapper = () => Messageable();
- type MessageablePerson = InstanceType>;
- export default MessageablePerson;`),
- tscLibPath + "/lib.d.ts": tscDefaultLibContent + "\n" + stringtestutil.Dedent(`
- type ReturnType any> = T extends (...args: any) => infer R ? R : any;
- type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;`),
- },
- commandLineArgs: []string{"--incremental"},
- edits: []*tscEdit{
- noChange,
- {
- caption: "modify public to protected",
- edit: func(sys *testSys) {
- sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "public", "protected")
- },
- },
- noChange,
- {
- caption: "modify protected to public",
- edit: func(sys *testSys) {
- sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "protected", "public")
- },
- },
- noChange,
- },
- },
- {
- subScenario: "when passing filename for buildinfo on commandline",
- files: FileMap{
- "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "target": "es5",
- "module": "commonjs"
- },
- "include": [
- "src/**/*.ts"
- ],
- }`),
- },
- commandLineArgs: []string{"--incremental", "--tsBuildInfoFile", ".tsbuildinfo", "--explainFiles"},
- edits: noChangeOnlyEdit,
- },
- {
- subScenario: "when passing rootDir from commandline",
- files: FileMap{
- "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "incremental": true,
- "outDir": "dist"
- }
- }`),
- },
- commandLineArgs: []string{"--rootDir", "src"},
- edits: noChangeOnlyEdit,
- },
- {
- subScenario: "with only dts files",
- files: FileMap{
- "/home/src/workspaces/project/src/main.d.ts": "export const x = 10;",
- "/home/src/workspaces/project/src/another.d.ts": "export const y = 10;",
- "/home/src/workspaces/project/tsconfig.json": "{}",
- },
- commandLineArgs: []string{"--incremental"},
- edits: []*tscEdit{
- noChange,
- {
- caption: "modify d.ts file",
- edit: func(sys *testSys) {
- sys.appendFile("/home/src/workspaces/project/src/main.d.ts", "export const xy = 100;")
- },
- },
- },
- },
- {
- subScenario: "when passing rootDir is in the tsconfig",
- files: FileMap{
- "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "incremental": true,
- "outDir": "dist",
- "rootDir": "./"
- }
- }`),
- },
- edits: noChangeOnlyEdit,
- },
- {
- subScenario: "tsbuildinfo has error",
- files: FileMap{
- "/home/src/workspaces/project/main.ts": "export const x = 10;",
- "/home/src/workspaces/project/tsconfig.json": "{}",
- "/home/src/workspaces/project/tsconfig.tsbuildinfo": "Some random string",
- },
- commandLineArgs: []string{"-i"},
- edits: []*tscEdit{
- {
- caption: "tsbuildinfo written has error",
- edit: func(sys *testSys) {
- sys.prependFile("/home/src/workspaces/project/tsconfig.tsbuildinfo", "Some random string")
- },
- },
- },
- },
- {
- subScenario: "when global file is added, the signatures are updated",
- files: FileMap{
- "/home/src/workspaces/project/src/main.ts": stringtestutil.Dedent(`
- ///
- ///
- function main() { }
- `),
- "/home/src/workspaces/project/src/anotherFileWithSameReferenes.ts": stringtestutil.Dedent(`
- ///
- ///
- function anotherFileWithSameReferenes() { }
- `),
- "/home/src/workspaces/project/src/filePresent.ts": `function something() { return 10; }`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": { "composite": true },
- "include": ["src/**/*.ts"],
- }`),
- },
- commandLineArgs: []string{},
- edits: []*tscEdit{
- noChange,
- {
- caption: "Modify main file",
- edit: func(sys *testSys) {
- sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`)
- },
- },
- {
- caption: "Modify main file again",
- edit: func(sys *testSys) {
- sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`)
- },
- },
- {
- caption: "Add new file and update main file",
- edit: func(sys *testSys) {
- sys.writeFileNoError(`/home/src/workspaces/project/src/newFile.ts`, "function foo() { return 20; }", false)
- sys.prependFile(
- `/home/src/workspaces/project/src/main.ts`,
- `///
-`,
- )
- sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `foo();`)
- },
- },
- {
- caption: "Write file that could not be resolved",
- edit: func(sys *testSys) {
- sys.writeFileNoError(`/home/src/workspaces/project/src/fileNotFound.ts`, "function something2() { return 20; }", false)
- },
- },
- {
- caption: "Modify main file",
- edit: func(sys *testSys) {
- sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`)
- },
- },
- },
- },
- {
- subScenario: "react-jsx-emit-mode with no backing types found doesnt crash",
- files: FileMap{
- "/home/src/workspaces/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
- "/home/src/workspaces/project/node_modules/@types/react/index.d.ts": stringtestutil.Dedent(`
- export {};
- declare global {
- namespace JSX {
- interface Element {}
- interface IntrinsicElements {
- div: {
- propA?: boolean;
- };
- }
- }
- }`), // doesn't contain a jsx-runtime definition
- "/home/src/workspaces/project/src/index.tsx": `export const App = () => ;`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "commonjs",
- "jsx": "react-jsx",
- "incremental": true,
- "jsxImportSource": "react"
- }
- }`),
- },
- },
- {
- subScenario: "react-jsx-emit-mode with no backing types found doesnt crash under --strict",
- files: FileMap{
- "/home/src/workspaces/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
- "/home/src/workspaces/project/node_modules/@types/react/index.d.ts": stringtestutil.Dedent(`
- export {};
- declare global {
- namespace JSX {
- interface Element {}
- interface IntrinsicElements {
- div: {
- propA?: boolean;
- };
- }
- }
- }`), // doesn't contain a jsx-runtime definition
- "/home/src/workspaces/project/src/index.tsx": `export const App = () => ;`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "commonjs",
- "jsx": "react-jsx",
- "incremental": true,
- "jsxImportSource": "react"
- }
- }`),
- },
- commandLineArgs: []string{"--strict"},
- },
- {
- subScenario: "change to type that gets used as global through export in another file",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true
- }
- }`),
- "/home/src/workspaces/project/class1.ts": stringtestutil.Dedent(`
- const a: MagicNumber = 1;
- console.log(a);`),
- "/home/src/workspaces/project/constants.ts": "export default 1;",
- "/home/src/workspaces/project/types.d.ts": `type MagicNumber = typeof import('./constants').default`,
- },
- edits: []*tscEdit{
- {
- caption: "Modify imports used in global file",
- edit: func(sys *testSys) {
- sys.writeFileNoError("/home/src/workspaces/project/constants.ts", "export default 2;", false)
- },
- expectedDiff: "Currently there is issue with d.ts emit for export default = 1 to widen in dts which is why we are not re-computing errors and results in incorrect error reporting",
- },
- },
- },
- {
- subScenario: "change to type that gets used as global through export in another file through indirect import",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true
- }
- }`),
- "/home/src/workspaces/project/class1.ts": stringtestutil.Dedent(`
- const a: MagicNumber = 1;
- console.log(a);`),
- "/home/src/workspaces/project/constants.ts": "export default 1;",
- "/home/src/workspaces/project/reexport.ts": `export { default as ConstantNumber } from "./constants"`,
- "/home/src/workspaces/project/types.d.ts": `type MagicNumber = typeof import('./reexport').ConstantNumber`,
- },
- edits: []*tscEdit{
- {
- caption: "Modify imports used in global file",
- edit: func(sys *testSys) {
- sys.writeFileNoError("/home/src/workspaces/project/constants.ts", "export default 2;", false)
- },
- expectedDiff: "Currently there is issue with d.ts emit for export default = 1 to widen in dts which is why we are not re-computing errors and results in incorrect error reporting",
- },
- },
- },
- {
- subScenario: "when file is deleted",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "outDir": "outDir"
- }
- }`),
- "/home/src/workspaces/project/file1.ts": `export class C { }`,
- "/home/src/workspaces/project/file2.ts": `export class D { }`,
- },
- edits: []*tscEdit{
- {
- caption: "delete file with imports",
- edit: func(sys *testSys) {
- err := sys.fsFromFileMap().Remove("/home/src/workspaces/project/file2.ts")
- if err != nil {
- panic(err)
- }
- },
- },
- },
- },
- {
- subScenario: "generates typerefs correctly",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "outDir": "outDir",
- "checkJs": true
- },
- "include": ["src"],
- }`),
- "/home/src/workspaces/project/src/box.ts": stringtestutil.Dedent(`
- export interface Box {
- unbox(): T
- }
- `),
- "/home/src/workspaces/project/src/bug.js": stringtestutil.Dedent(`
- import * as B from "./box.js"
- import * as W from "./wrap.js"
-
- /**
- * @template {object} C
- * @param {C} source
- * @returns {W.Wrap}
- */
- const wrap = source => {
- throw source
- }
-
- /**
- * @returns {B.Box}
- */
- const box = (n = 0) => ({ unbox: () => n })
-
- export const bug = wrap({ n: box(1) });
- `),
- "/home/src/workspaces/project/src/wrap.ts": stringtestutil.Dedent(`
- export type Wrap = {
- [K in keyof C]: { wrapped: C[K] }
- }
- `),
- },
- edits: []*tscEdit{
- {
- caption: "modify js file",
- edit: func(sys *testSys) {
- sys.appendFile("/home/src/workspaces/project/src/bug.js", `export const something = 1;`)
- },
- },
- },
- },
- getConstEnumTest(`
- export const enum A {
- ONE = 1
- }
- `, "/home/src/workspaces/project/b.d.ts", ""),
- getConstEnumTest(`
- export const enum AWorker {
- ONE = 1
- }
- export { AWorker as A };
- `, "/home/src/workspaces/project/b.d.ts", " aliased"),
- getConstEnumTest(`export { AWorker as A } from "./worker";`, "/home/src/workspaces/project/worker.d.ts", " aliased in different file"),
- {
- subScenario: "option changes with composite",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- }
- }`),
- "/home/src/workspaces/project/a.ts": `export const a = 10;const aLocal = 10;`,
- "/home/src/workspaces/project/b.ts": `export const b = 10;const bLocal = 10;`,
- "/home/src/workspaces/project/c.ts": `import { a } from "./a";export const c = a;`,
- "/home/src/workspaces/project/d.ts": `import { b } from "./b";export const d = b;`,
- },
- edits: []*tscEdit{
- {
- caption: "with sourceMap",
- commandLineArgs: []string{"--sourceMap"},
- },
- {
- caption: "should re-emit only js so they dont contain sourcemap",
- },
- {
- caption: "with declaration should not emit anything",
- commandLineArgs: []string{"--declaration"},
- // discrepancyExplanation: () => [
- // `Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/-/g, "")}`,
- // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
- // ],
- },
- noChange,
- {
- caption: "with declaration and declarationMap",
- commandLineArgs: []string{"--declaration", "--declarationMap"},
- },
- {
- caption: "should re-emit only dts so they dont contain sourcemap",
- },
- {
- caption: "with emitDeclarationOnly should not emit anything",
- commandLineArgs: []string{"--emitDeclarationOnly"},
- // discrepancyExplanation: () => [
- // `Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/-/g, "")}`,
- // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
- // ],
- },
- noChange,
- {
- caption: "local change",
- edit: func(sys *testSys) {
- sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10")
- },
- },
- {
- caption: "with declaration should not emit anything",
- commandLineArgs: []string{"--declaration"},
- // discrepancyExplanation: () => [
- // `Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/-/g, "")}`,
- // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
- // ],
- },
- {
- caption: "with inlineSourceMap",
- commandLineArgs: []string{"--inlineSourceMap"},
- },
- {
- caption: "with sourceMap",
- commandLineArgs: []string{"--sourceMap"},
- },
- {
- caption: "declarationMap enabling",
- edit: func(sys *testSys) {
- sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", `"composite": true,`, `"composite": true, "declarationMap": true`)
- },
- },
- {
- caption: "with sourceMap should not emit d.ts",
- commandLineArgs: []string{"--sourceMap"},
- },
- },
- },
- {
- subScenario: "option changes with incremental",
- files: FileMap{
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "incremental": true,
- }
- }`),
- "/home/src/workspaces/project/a.ts": `export const a = 10;const aLocal = 10;`,
- "/home/src/workspaces/project/b.ts": `export const b = 10;const bLocal = 10;`,
- "/home/src/workspaces/project/c.ts": `import { a } from "./a";export const c = a;`,
- "/home/src/workspaces/project/d.ts": `import { b } from "./b";export const d = b;`,
- },
- edits: []*tscEdit{
- {
- caption: "with sourceMap",
- commandLineArgs: []string{"--sourceMap"},
- },
- {
- caption: "should re-emit only js so they dont contain sourcemap",
- },
- {
- caption: "with declaration, emit Dts and should not emit js",
- commandLineArgs: []string{"--declaration"},
- },
- {
- caption: "with declaration and declarationMap",
- commandLineArgs: []string{"--declaration", "--declarationMap"},
- },
- {
- caption: "no change",
- // discrepancyExplanation: () => [
- // `Clean build tsbuildinfo will have compilerOptions {}`,
- // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option declaration and declarationMap`,
- // ],
- },
- {
- caption: "local change",
- edit: func(sys *testSys) {
- sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10")
- },
- },
- {
- caption: "with declaration and declarationMap",
- commandLineArgs: []string{"--declaration", "--declarationMap"},
- },
- {
- caption: "no change",
- // discrepancyExplanation: () => [
- // `Clean build tsbuildinfo will have compilerOptions {}`,
- // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option declaration and declarationMap`,
- // ],
- },
- {
- caption: "with inlineSourceMap",
- commandLineArgs: []string{"--inlineSourceMap"},
- },
- {
- caption: "with sourceMap",
- commandLineArgs: []string{"--sourceMap"},
- },
- {
- caption: "emit js files",
- },
- {
- caption: "with declaration and declarationMap",
- commandLineArgs: []string{"--declaration", "--declarationMap"},
- },
- {
- caption: "with declaration and declarationMap, should not re-emit",
- commandLineArgs: []string{"--declaration", "--declarationMap"},
- },
- },
- },
- }
-
- for _, test := range testCases {
- test.run(t, "incremental")
- }
-}
-
-func getConstEnumTest(bdsContents string, changeEnumFile string, testSuffix string) *tscInput {
- return &tscInput{
- subScenario: "const enums" + testSuffix,
- files: FileMap{
- "/home/src/workspaces/project/a.ts": stringtestutil.Dedent(`
- import {A} from "./c"
- let a = A.ONE
- `),
- "/home/src/workspaces/project/b.d.ts": stringtestutil.Dedent(bdsContents),
- "/home/src/workspaces/project/c.ts": stringtestutil.Dedent(`
- import {A} from "./b"
- let b = A.ONE
- export {A}
- `),
- "/home/src/workspaces/project/worker.d.ts": stringtestutil.Dedent(`
- export const enum AWorker {
- ONE = 1
- }
- `),
- },
- commandLineArgs: []string{"-i", `a.ts`, "--tsbuildinfofile", "a.tsbuildinfo"},
- edits: []*tscEdit{
- {
- caption: "change enum value",
- edit: func(sys *testSys) {
- sys.replaceFileText(changeEnumFile, "1", "2")
- },
- },
- {
- caption: "change enum value again",
- edit: func(sys *testSys) {
- sys.replaceFileText(changeEnumFile, "2", "3")
- },
- },
- {
- caption: "something else changes in b.d.ts",
- edit: func(sys *testSys) {
- sys.appendFile("/home/src/workspaces/project/b.d.ts", "export const randomThing = 10;")
- },
- },
- {
- caption: "something else changes in b.d.ts again",
- edit: func(sys *testSys) {
- sys.appendFile("/home/src/workspaces/project/b.d.ts", "export const randomThing2 = 10;")
- },
- },
- },
- }
-}
diff --git a/internal/execute/tscnocheck_test.go b/internal/execute/tscnocheck_test.go
deleted file mode 100644
index 45d4846d84..0000000000
--- a/internal/execute/tscnocheck_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package execute_test
-
-import (
- "testing"
-
- "github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
-)
-
-type noCheckScenario struct {
- subscenario string
- aText string
-}
-
-func TestNoCheck(t *testing.T) {
- t.Parallel()
- cases := []noCheckScenario{
- {"syntax errors", `export const a = "hello`},
- {"semantic errors", `export const a: number = "hello";`},
- {"dts errors", `export const a = class { private p = 10; };`},
- }
- for _, c := range cases {
- (&tscInput{
- subScenario: c.subscenario,
- files: FileMap{
- "/home/src/workspaces/project/a.ts": c.aText,
- "/home/src/workspaces/project/b.ts": `export const b = 10;`,
- "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "declaration": true,
- }
- }`),
- // incremental: undefined, true
- },
- commandLineArgs: []string{"--noCheck"},
- }).run(t, "noCheck")
- }
-}
diff --git a/internal/execute/tscprojectreferences_test.go b/internal/execute/tscprojectreferences_test.go
deleted file mode 100644
index 43469158ad..0000000000
--- a/internal/execute/tscprojectreferences_test.go
+++ /dev/null
@@ -1,334 +0,0 @@
-package execute_test
-
-import (
- "testing"
-
- "github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
-)
-
-func TestProjectReferences(t *testing.T) {
- t.Parallel()
- cases := []tscInput{
- {
- subScenario: "when project references composite project with noEmit",
- files: FileMap{
- "/home/src/workspaces/solution/utils/index.ts": "export const x = 10;",
- "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "noEmit": true
- }
- }`),
- "/home/src/workspaces/solution/project/index.ts": `import { x } from "../utils";`,
- "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "references": [
- { "path": "../utils" },
- ],
- }`),
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "project"},
- },
- {
- subScenario: "when project references composite",
- files: FileMap{
- "/home/src/workspaces/solution/utils/index.ts": "export const x = 10;",
- "/home/src/workspaces/solution/utils/index.d.ts": "export declare const x = 10;",
- "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true
- }
- }`),
- "/home/src/workspaces/solution/project/index.ts": `import { x } from "../utils";`,
- "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "references": [
- { "path": "../utils" },
- ],
- }`),
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "project"},
- },
- {
- subScenario: "when project reference is not built",
- files: FileMap{
- "/home/src/workspaces/solution/utils/index.ts": "export const x = 10;",
- "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true
- }
- }`),
- "/home/src/workspaces/solution/project/index.ts": `import { x } from "../utils";`,
- "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "references": [
- { "path": "../utils" },
- ],
- }`),
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "project"},
- },
- {
- subScenario: "when project contains invalid project reference",
- files: FileMap{
- "/home/src/workspaces/solution/project/index.ts": `export const x = 10;`,
- "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "references": [
- { "path": "../utils" },
- ],
- }`),
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "project"},
- },
- {
- subScenario: "default import interop uses referenced project settings",
- files: FileMap{
- "/home/src/workspaces/project/node_modules/ambiguous-package/package.json": stringtestutil.Dedent(`
- {
- "name": "ambiguous-package"
- }`),
- "/home/src/workspaces/project/node_modules/ambiguous-package/index.d.ts": "export declare const ambiguous: number;",
- "/home/src/workspaces/project/node_modules/esm-package/package.json": stringtestutil.Dedent(`
- {
- "name": "esm-package",
- "type": "module"
- }`),
- "/home/src/workspaces/project/node_modules/esm-package/index.d.ts": "export declare const esm: number;",
- "/home/src/workspaces/project/lib/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "declaration": true,
- "rootDir": "src",
- "outDir": "dist",
- "module": "esnext",
- "moduleResolution": "bundler",
- },
- "include": ["src"],
- }`),
- "/home/src/workspaces/project/lib/src/a.ts": "export const a = 0;",
- "/home/src/workspaces/project/lib/dist/a.d.ts": "export declare const a = 0;",
- "/home/src/workspaces/project/app/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "esnext",
- "moduleResolution": "bundler",
- "rootDir": "src",
- "outDir": "dist",
- },
- "include": ["src"],
- "references": [
- { "path": "../lib" },
- ],
- }`),
- "/home/src/workspaces/project/app/src/local.ts": "export const local = 0;",
- "/home/src/workspaces/project/app/src/index.ts": stringtestutil.Dedent(`
- import local from "./local"; // Error
- import esm from "esm-package"; // Error
- import referencedSource from "../../lib/src/a"; // Error
- import referencedDeclaration from "../../lib/dist/a"; // Error
- import ambiguous from "ambiguous-package"; // Ok`),
- },
- commandLineArgs: []string{"--p", "app", "--pretty", "false"},
- },
- {
- subScenario: "referencing ambient const enum from referenced project with preserveConstEnums",
- files: FileMap{
- "/home/src/workspaces/solution/utils/index.ts": "export const enum E { A = 1 }",
- "/home/src/workspaces/solution/utils/index.d.ts": "export declare const enum E { A = 1 }",
- "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "declaration": true,
- "preserveConstEnums": true,
- },
- }`),
- "/home/src/workspaces/solution/project/index.ts": `import { E } from "../utils"; E.A;`,
- "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "isolatedModules": true,
- },
- "references": [
- { "path": "../utils" },
- ],
- }`),
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "project"},
- },
- {
- subScenario: "importing const enum from referenced project with preserveConstEnums and verbatimModuleSyntax",
- files: FileMap{
- "/home/src/workspaces/solution/preserve/index.ts": "export const enum E { A = 1 }",
- "/home/src/workspaces/solution/preserve/index.d.ts": "export declare const enum E { A = 1 }",
- "/home/src/workspaces/solution/preserve/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "declaration": true,
- "preserveConstEnums": true,
- },
- }`),
- "/home/src/workspaces/solution/no-preserve/index.ts": "export const enum E { A = 1 }",
- "/home/src/workspaces/solution/no-preserve/index.d.ts": "export declare const enum F { A = 1 }",
- "/home/src/workspaces/solution/no-preserve/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "declaration": true,
- "preserveConstEnums": false,
- },
- }`),
- "/home/src/workspaces/solution/project/index.ts": stringtestutil.Dedent(`
- import { E } from "../preserve";
- import { F } from "../no-preserve";
- E.A;
- F.A;`),
- "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "preserve",
- "verbatimModuleSyntax": true,
- },
- "references": [
- { "path": "../preserve" },
- { "path": "../no-preserve" },
- ],
- }`),
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "project", "--pretty", "false"},
- },
- {
- subScenario: "rewriteRelativeImportExtensionsProjectReferences1",
- files: FileMap{
- "/home/src/workspaces/packages/common/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "composite": true,
- "rootDir": "src",
- "outDir": "dist",
- "module": "nodenext"
- }
- }`),
- "/home/src/workspaces/packages/common/package.json": stringtestutil.Dedent(`
- {
- "name": "common",
- "version": "1.0.0",
- "type": "module",
- "exports": {
- ".": {
- "source": "./src/index.ts",
- "default": "./dist/index.js"
- }
- }
- }`),
- "/home/src/workspaces/packages/common/src/index.ts": "export {};",
- "/home/src/workspaces/packages/common/dist/index.d.ts": "export {};",
- "/home/src/workspaces/packages/main/tsconfig.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "nodenext",
- "rewriteRelativeImportExtensions": true,
- "rootDir": "src",
- "outDir": "dist"
- },
- "references": [
- { "path": "../common" }
- ]
- }`),
- "/home/src/workspaces/packages/main/package.json": stringtestutil.Dedent(`
- {
- "type": "module"
- }`),
- "/home/src/workspaces/packages/main/src/index.ts": `import {} from "../../common/src/index.ts";`,
- },
- cwd: "/home/src/workspaces",
- commandLineArgs: []string{"-p", "packages/main", "--pretty", "false"},
- },
- {
- subScenario: "rewriteRelativeImportExtensionsProjectReferences2",
- files: FileMap{
- "/home/src/workspaces/solution/src/tsconfig-base.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "nodenext",
- "composite": true,
- "rootDir": ".",
- "outDir": "../dist",
- "rewriteRelativeImportExtensions": true
- }
- }`),
- "/home/src/workspaces/solution/src/compiler/tsconfig.json": stringtestutil.Dedent(`
- {
- "extends": "../tsconfig-base.json",
- "compilerOptions": {}
- }`),
- "/home/src/workspaces/solution/src/compiler/parser.ts": "export {};",
- "/home/src/workspaces/solution/dist/compiler/parser.d.ts": "export {};",
- "/home/src/workspaces/solution/src/services/tsconfig.json": stringtestutil.Dedent(`
- {
- "extends": "../tsconfig-base.json",
- "compilerOptions": {},
- "references": [
- { "path": "../compiler" }
- ]
- }`),
- "/home/src/workspaces/solution/src/services/services.ts": `import {} from "../compiler/parser.ts";`,
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "src/services", "--pretty", "false"},
- },
- {
- subScenario: "rewriteRelativeImportExtensionsProjectReferences3",
- files: FileMap{
- "/home/src/workspaces/solution/src/tsconfig-base.json": stringtestutil.Dedent(`
- {
- "compilerOptions": {
- "module": "nodenext",
- "composite": true,
- "rewriteRelativeImportExtensions": true
- }
- }`),
- "/home/src/workspaces/solution/src/compiler/tsconfig.json": stringtestutil.Dedent(`
- {
- "extends": "../tsconfig-base.json",
- "compilerOptions": {
- "rootDir": ".",
- "outDir": "../../dist/compiler"
- }
- }`),
- "/home/src/workspaces/solution/src/compiler/parser.ts": "export {};",
- "/home/src/workspaces/solution/dist/compiler/parser.d.ts": "export {};",
- "/home/src/workspaces/solution/src/services/tsconfig.json": stringtestutil.Dedent(`
- {
- "extends": "../tsconfig-base.json",
- "compilerOptions": {
- "rootDir": ".",
- "outDir": "../../dist/services"
- },
- "references": [
- { "path": "../compiler" }
- ]
- }`),
- "/home/src/workspaces/solution/src/services/services.ts": `import {} from "../compiler/parser.ts";`,
- },
- cwd: "/home/src/workspaces/solution",
- commandLineArgs: []string{"--p", "src/services", "--pretty", "false"},
- },
- }
-
- for _, c := range cases {
- c.run(t, "projectReferences")
- }
-}
diff --git a/internal/testutil/incrementaltestutil/fs.go b/internal/execute/tsctests/fs.go
similarity index 55%
rename from internal/testutil/incrementaltestutil/fs.go
rename to internal/execute/tsctests/fs.go
index d238229955..03c653a2a8 100644
--- a/internal/testutil/incrementaltestutil/fs.go
+++ b/internal/execute/tsctests/fs.go
@@ -1,23 +1,37 @@
-package incrementaltestutil
+package tsctests
import (
"fmt"
"github.com/go-json-experiment/json"
+ "github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/core"
- "github.com/microsoft/typescript-go/internal/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
"github.com/microsoft/typescript-go/internal/testutil/harnessutil"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
)
-type FsHandlingBuildInfo struct {
+type testFs struct {
vfs.FS
+ defaultLibs *collections.SyncSet[string]
+ writtenFiles collections.SyncSet[string]
+}
+
+func (f *testFs) removeIgnoreLibPath(path string) {
+ if f.defaultLibs != nil && f.defaultLibs.Has(path) {
+ f.defaultLibs.Delete(path)
+ }
}
// ReadFile reads the file specified by path and returns the content.
// If the file fails to be read, ok will be false.
-func (f *FsHandlingBuildInfo) ReadFile(path string) (contents string, ok bool) {
+func (f *testFs) ReadFile(path string) (contents string, ok bool) {
+ f.removeIgnoreLibPath(path)
+ return f.readFileHandlingBuildInfo(path)
+}
+
+func (f *testFs) readFileHandlingBuildInfo(path string) (contents string, ok bool) {
contents, ok = f.FS.ReadFile(path)
if ok && tspath.FileExtensionIs(path, tspath.ExtensionTsBuildInfo) {
// read buildinfo and modify version
@@ -35,7 +49,13 @@ func (f *FsHandlingBuildInfo) ReadFile(path string) (contents string, ok bool) {
return contents, ok
}
-func (f *FsHandlingBuildInfo) WriteFile(path string, data string, writeByteOrderMark bool) error {
+func (f *testFs) WriteFile(path string, data string, writeByteOrderMark bool) error {
+ f.removeIgnoreLibPath(path)
+ f.writtenFiles.Add(path)
+ return f.writeFileHandlingBuildInfo(path, data, writeByteOrderMark)
+}
+
+func (f *testFs) writeFileHandlingBuildInfo(path string, data string, writeByteOrderMark bool) error {
if tspath.FileExtensionIs(path, tspath.ExtensionTsBuildInfo) {
var buildInfo incremental.BuildInfo
if err := json.Unmarshal([]byte(data), &buildInfo); err == nil {
@@ -49,10 +69,18 @@ func (f *FsHandlingBuildInfo) WriteFile(path string, data string, writeByteOrder
data = string(newData)
}
// Write readable build info version
- if err := f.FS.WriteFile(path+".readable.baseline.txt", toReadableBuildInfo(&buildInfo, data), false); err != nil {
+ if err := f.WriteFile(path+".readable.baseline.txt", toReadableBuildInfo(&buildInfo, data), false); err != nil {
return fmt.Errorf("testFs.WriteFile: failed to write readable build info: %w", err)
}
+ } else {
+ panic("testFs.WriteFile: failed to unmarshal build info: - use underlying FS's write method if this is intended use for testcase" + err.Error())
}
}
return f.FS.WriteFile(path, data, writeByteOrderMark)
}
+
+// Removes `path` and all its contents. Will return the first error it encounters.
+func (f *testFs) Remove(path string) error {
+ f.removeIgnoreLibPath(path)
+ return f.FS.Remove(path)
+}
diff --git a/internal/testutil/incrementaltestutil/readablebuildinfo.go b/internal/execute/tsctests/readablebuildinfo.go
similarity index 82%
rename from internal/testutil/incrementaltestutil/readablebuildinfo.go
rename to internal/execute/tsctests/readablebuildinfo.go
index dbfa965087..3969ac5f75 100644
--- a/internal/testutil/incrementaltestutil/readablebuildinfo.go
+++ b/internal/execute/tsctests/readablebuildinfo.go
@@ -1,4 +1,4 @@
-package incrementaltestutil
+package tsctests
import (
"fmt"
@@ -8,7 +8,7 @@ import (
"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/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
"github.com/microsoft/typescript-go/internal/jsonutil"
)
@@ -17,9 +17,9 @@ type readableBuildInfo struct {
Version string `json:"version,omitzero"`
// Common between incremental and tsc -b buildinfo for non incremental programs
- Errors bool `json:"errors,omitzero"`
- CheckPending bool `json:"checkPending,omitzero"`
- // Root []BuildInfoRoot `json:"root,omitzero"`
+ Errors bool `json:"errors,omitzero"`
+ CheckPending bool `json:"checkPending,omitzero"`
+ Root []*readableBuildInfoRoot `json:"root,omitzero"`
// IncrementalProgram info
FileNames []string `json:"fileNames,omitzero"`
@@ -33,8 +33,16 @@ type readableBuildInfo struct {
AffectedFilesPendingEmit []*readableBuildInfoFilePendingEmit `json:"affectedFilesPendingEmit,omitzero"`
LatestChangedDtsFile string `json:"latestChangedDtsFile,omitzero"` // Because this is only output file in the program, we dont need fileId to deduplicate name
EmitSignatures []*readableBuildInfoEmitSignature `json:"emitSignatures,omitzero"`
- // resolvedRoot: readonly IncrementalBuildInfoResolvedRoot[] | undefined;
- Size int `json:"size,omitzero"` // Size of the build info file
+ ResolvedRoot []*readableBuildInfoResolvedRoot `json:"resolvedRoot,omitzero"`
+ Size int `json:"size,omitzero"` // Size of the build info file
+
+ // NonIncrementalProgram info
+ SemanticErrors bool `json:"semanticErrors,omitzero"`
+}
+
+type readableBuildInfoRoot struct {
+ Files []string `json:"files,omitzero"`
+ Original *incremental.BuildInfoRoot `json:"original,omitzero"`
}
type readableBuildInfoFileInfo struct {
@@ -86,14 +94,15 @@ func (r *readableBuildInfoDiagnosticsOfFile) UnmarshalJSON(data []byte) error {
if !ok {
return fmt.Errorf("invalid fileId in readableBuildInfoDiagnosticsOfFile: expected string, got %T", fileIdAndDiagnostics[0])
}
- if diagnostics, ok := fileIdAndDiagnostics[1].([]*readableBuildInfoDiagnostic); ok {
+ if diagnostics, ok := fileIdAndDiagnostics[1].([]*readableBuildInfoDiagnostic); !ok {
+ return fmt.Errorf("invalid diagnostics in readableBuildInfoDiagnosticsOfFile: expected []*readableBuildInfoDiagnostic, got %T", fileIdAndDiagnostics[1])
+ } else {
*r = readableBuildInfoDiagnosticsOfFile{
file: file,
diagnostics: diagnostics,
}
return nil
}
- return fmt.Errorf("invalid diagnostics in readableBuildInfoDiagnosticsOfFile: expected []*readableBuildInfoDiagnostic, got %T", fileIdAndDiagnostics[1])
}
type readableBuildInfoSemanticDiagnostic struct {
@@ -110,20 +119,20 @@ func (r *readableBuildInfoSemanticDiagnostic) MarshalJSON() ([]byte, error) {
func (r *readableBuildInfoSemanticDiagnostic) UnmarshalJSON(data []byte) error {
var file string
- if err := json.Unmarshal(data, &file); err == nil {
- *r = readableBuildInfoSemanticDiagnostic{
- file: file,
+ if err := json.Unmarshal(data, &file); err != nil {
+ var diagnostics readableBuildInfoDiagnosticsOfFile
+ if err := json.Unmarshal(data, &diagnostics); err != nil {
+ return fmt.Errorf("invalid readableBuildInfoSemanticDiagnostic: %s", data)
}
- return nil
- }
- var diagnostics readableBuildInfoDiagnosticsOfFile
- if err := json.Unmarshal(data, &diagnostics); err == nil {
*r = readableBuildInfoSemanticDiagnostic{
diagnostics: &diagnostics,
}
return nil
}
- return fmt.Errorf("invalid readableBuildInfoSemanticDiagnostic: %s", data)
+ *r = readableBuildInfoSemanticDiagnostic{
+ file: file,
+ }
+ return nil
}
type readableBuildInfoFilePendingEmit struct {
@@ -174,6 +183,27 @@ type readableBuildInfoEmitSignature struct {
Original *incremental.BuildInfoEmitSignature `json:"original,omitzero"`
}
+type readableBuildInfoResolvedRoot struct {
+ Resolved string
+ Root string
+}
+
+func (b *readableBuildInfoResolvedRoot) MarshalJSON() ([]byte, error) {
+ return json.Marshal([2]string{b.Resolved, b.Root})
+}
+
+func (b *readableBuildInfoResolvedRoot) UnmarshalJSON(data []byte) error {
+ var resolvedAndRoot [2]string
+ if err := json.Unmarshal(data, &resolvedAndRoot); err != nil {
+ return fmt.Errorf("invalid BuildInfoResolvedRoot: %s", data)
+ }
+ *b = readableBuildInfoResolvedRoot{
+ Resolved: resolvedAndRoot[0],
+ Root: resolvedAndRoot[1],
+ }
+ return nil
+}
+
func toReadableBuildInfo(buildInfo *incremental.BuildInfo, buildInfoText string) string {
readable := readableBuildInfo{
buildInfo: buildInfo,
@@ -183,9 +213,11 @@ func toReadableBuildInfo(buildInfo *incremental.BuildInfo, buildInfoText string)
FileNames: buildInfo.FileNames,
Options: buildInfo.Options,
LatestChangedDtsFile: buildInfo.LatestChangedDtsFile,
+ SemanticErrors: buildInfo.SemanticErrors,
Size: len(buildInfoText),
}
readable.setFileInfos()
+ readable.setRoot()
readable.setFileIdsList()
readable.setReferencedMap()
readable.setChangeFileSet()
@@ -193,6 +225,7 @@ func toReadableBuildInfo(buildInfo *incremental.BuildInfo, buildInfoText string)
readable.setEmitDiagnostics()
readable.setAffectedFilesPendingEmit()
readable.setEmitSignatures()
+ readable.setResolvedRoot()
contents, err := jsonutil.MarshalIndent(&readable, "", " ")
if err != nil {
panic("readableBuildInfo: failed to marshal readable build info: " + err.Error())
@@ -256,6 +289,26 @@ func (r *readableBuildInfo) setFileInfos() {
})
}
+func (r *readableBuildInfo) setRoot() {
+ r.Root = core.Map(r.buildInfo.Root, func(original *incremental.BuildInfoRoot) *readableBuildInfoRoot {
+ var files []string
+ if original.NonIncremental != "" {
+ files = []string{original.NonIncremental}
+ } else if original.End == 0 {
+ files = []string{r.toFilePath(original.Start)}
+ } else {
+ files = make([]string, 0, original.End-original.Start+1)
+ for i := original.Start; i <= original.End; i++ {
+ files = append(files, r.toFilePath(i))
+ }
+ }
+ return &readableBuildInfoRoot{
+ Files: files,
+ Original: original,
+ }
+ })
+}
+
func (r *readableBuildInfo) setFileIdsList() {
r.FileIdsList = core.Map(r.buildInfo.FileIdsList, func(ids []incremental.BuildInfoFileId) []string {
return core.Map(ids, r.toFilePath)
@@ -358,3 +411,12 @@ func (r *readableBuildInfo) setEmitSignatures() {
}
})
}
+
+func (r *readableBuildInfo) setResolvedRoot() {
+ r.ResolvedRoot = core.Map(r.buildInfo.ResolvedRoot, func(original *incremental.BuildInfoResolvedRoot) *readableBuildInfoResolvedRoot {
+ return &readableBuildInfoResolvedRoot{
+ Resolved: r.toFilePath(original.Resolved),
+ Root: r.toFilePath(original.Root),
+ }
+ })
+}
diff --git a/internal/execute/tsctestrunner_test.go b/internal/execute/tsctests/runner.go
similarity index 87%
rename from internal/execute/tsctestrunner_test.go
rename to internal/execute/tsctests/runner.go
index d6546c7e06..efaf923e50 100644
--- a/internal/execute/tsctestrunner_test.go
+++ b/internal/execute/tsctests/runner.go
@@ -1,4 +1,4 @@
-package execute_test
+package tsctests
import (
"fmt"
@@ -9,6 +9,7 @@ import (
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/execute"
+ "github.com/microsoft/typescript-go/internal/execute/tsc"
"github.com/microsoft/typescript-go/internal/testutil/baseline"
"github.com/microsoft/typescript-go/internal/tspath"
)
@@ -39,21 +40,21 @@ type tscInput struct {
windowsStyleRoot string
}
-func (test *tscInput) executeCommand(sys *testSys, baselineBuilder *strings.Builder, commandLineArgs []string) execute.CommandLineResult {
+func (test *tscInput) executeCommand(sys *testSys, baselineBuilder *strings.Builder, commandLineArgs []string) tsc.CommandLineResult {
fmt.Fprint(baselineBuilder, "tsgo ", strings.Join(commandLineArgs, " "), "\n")
result := execute.CommandLine(sys, commandLineArgs, sys)
switch result.Status {
- case execute.ExitStatusSuccess:
+ case tsc.ExitStatusSuccess:
baselineBuilder.WriteString("ExitStatus:: Success")
- case execute.ExitStatusDiagnosticsPresent_OutputsSkipped:
+ case tsc.ExitStatusDiagnosticsPresent_OutputsSkipped:
baselineBuilder.WriteString("ExitStatus:: DiagnosticsPresent_OutputsSkipped")
- case execute.ExitStatusDiagnosticsPresent_OutputsGenerated:
+ case tsc.ExitStatusDiagnosticsPresent_OutputsGenerated:
baselineBuilder.WriteString("ExitStatus:: DiagnosticsPresent_OutputsGenerated")
- case execute.ExitStatusInvalidProject_OutputsSkipped:
+ case tsc.ExitStatusInvalidProject_OutputsSkipped:
baselineBuilder.WriteString("ExitStatus:: InvalidProject_OutputsSkipped")
- case execute.ExitStatusProjectReferenceCycle_OutputsSkipped:
+ case tsc.ExitStatusProjectReferenceCycle_OutputsSkipped:
baselineBuilder.WriteString("ExitStatus:: ProjectReferenceCycle_OutputsSkipped")
- case execute.ExitStatusNotImplemented:
+ case tsc.ExitStatusNotImplemented:
baselineBuilder.WriteString("ExitStatus:: NotImplemented")
default:
panic(fmt.Sprintf("UnknownExitStatus %d", result.Status))
@@ -63,11 +64,11 @@ func (test *tscInput) executeCommand(sys *testSys, baselineBuilder *strings.Buil
func (test *tscInput) run(t *testing.T, scenario string) {
t.Helper()
- t.Run(test.subScenario, func(t *testing.T) {
+ t.Run(test.getBaselineSubFolder()+"/"+test.subScenario, func(t *testing.T) {
t.Parallel()
// initial test tsc compile
baselineBuilder := &strings.Builder{}
- sys := newTestSys(test)
+ sys := newTestSys(test, false)
fmt.Fprint(
baselineBuilder,
"currentDirectory::",
@@ -79,7 +80,7 @@ func (test *tscInput) run(t *testing.T, scenario string) {
sys.baselineFSwithDiff(baselineBuilder)
result := test.executeCommand(sys, baselineBuilder, test.commandLineArgs)
sys.serializeState(baselineBuilder)
- sys.baselineProgram(baselineBuilder, result.IncrementalProgram, result.Watcher)
+ sys.baselinePrograms(baselineBuilder, result.IncrementalProgram, result.Watcher)
var unexpectedDiff string
for index, do := range test.edits {
@@ -94,18 +95,18 @@ func (test *tscInput) run(t *testing.T, scenario string) {
}
sys.baselineFSwithDiff(baselineBuilder)
- var editResult execute.CommandLineResult
+ var editResult tsc.CommandLineResult
if result.Watcher == nil {
editResult = test.executeCommand(sys, baselineBuilder, commandLineArgs)
} else {
result.Watcher.DoCycle()
}
sys.serializeState(baselineBuilder)
- sys.baselineProgram(baselineBuilder, editResult.IncrementalProgram, result.Watcher)
+ sys.baselinePrograms(baselineBuilder, editResult.IncrementalProgram, result.Watcher)
})
wg.Queue(func() {
// Compute build with all the edits
- nonIncrementalSys = newTestSys(test)
+ nonIncrementalSys = newTestSys(test, true)
for i := range index + 1 {
if test.edits[i].edit != nil {
test.edits[i].edit(nonIncrementalSys)
@@ -137,7 +138,7 @@ func (test *tscInput) run(t *testing.T, scenario string) {
func getDiffForIncremental(incrementalSys *testSys, nonIncrementalSys *testSys) string {
var diffBuilder strings.Builder
- nonIncrementalOutputs := nonIncrementalSys.testFs().writtenFiles.ToSlice()
+ nonIncrementalOutputs := nonIncrementalSys.fs.writtenFiles.ToSlice()
slices.Sort(nonIncrementalOutputs)
for _, nonIncrementalOutput := range nonIncrementalOutputs {
if tspath.FileExtensionIs(nonIncrementalOutput, tspath.ExtensionTsBuildInfo) ||
diff --git a/internal/execute/testsys_test.go b/internal/execute/tsctests/sys.go
similarity index 68%
rename from internal/execute/testsys_test.go
rename to internal/execute/tsctests/sys.go
index 44875635a9..90b269bac0 100644
--- a/internal/execute/testsys_test.go
+++ b/internal/execute/tsctests/sys.go
@@ -1,4 +1,4 @@
-package execute_test
+package tsctests
import (
"fmt"
@@ -12,11 +12,11 @@ import (
"time"
"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/execute"
- "github.com/microsoft/typescript-go/internal/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/tsc"
"github.com/microsoft/typescript-go/internal/testutil/harnessutil"
- "github.com/microsoft/typescript-go/internal/testutil/incrementaltestutil"
"github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
@@ -54,6 +54,16 @@ interface Symbol {
declare const console: { log(msg: any): void; };
`)
+func getTestLibPathFor(libName string) string {
+ var libFile string
+ if value, ok := tsoptions.LibMap.Get(libName); ok {
+ libFile = value.(string)
+ } else {
+ libFile = "lib." + libName + ".d.ts"
+ }
+ return tscLibPath + "/" + libFile
+}
+
type TestClock struct {
start time.Time
now time.Time
@@ -74,7 +84,18 @@ func (t *TestClock) SinceStart() time.Duration {
return t.Now().Sub(t.start)
}
-func newTestSys(tscInput *tscInput) *testSys {
+func NewTscSystem(files FileMap, useCaseSensitiveFileNames bool, cwd string) *testSys {
+ clock := &TestClock{start: time.Now()}
+ return &testSys{
+ fs: &testFs{
+ FS: vfstest.FromMapWithClock(files, useCaseSensitiveFileNames, clock),
+ },
+ cwd: cwd,
+ clock: clock,
+ }
+}
+
+func newTestSys(tscInput *tscInput, forIncrementalCorrectness bool) *testSys {
cwd := tscInput.cwd
if cwd == "" {
cwd = "/home/src/workspaces/project"
@@ -84,23 +105,15 @@ func newTestSys(tscInput *tscInput) *testSys {
libPath = tscInput.windowsStyleRoot + libPath[1:]
}
currentWrite := &strings.Builder{}
- clock := &TestClock{start: time.Now()}
- sys := &testSys{
- fs: &incrementaltestutil.FsHandlingBuildInfo{
- FS: &testFs{
- FS: vfstest.FromMapWithClock(tscInput.files, !tscInput.ignoreCase, clock),
- },
- },
- defaultLibraryPath: libPath,
- cwd: cwd,
- currentWrite: currentWrite,
- tracer: harnessutil.NewTracerForBaselining(tspath.ComparePathsOptions{
- UseCaseSensitiveFileNames: !tscInput.ignoreCase,
- CurrentDirectory: cwd,
- }, currentWrite),
- clock: clock,
- env: tscInput.env,
- }
+ sys := NewTscSystem(tscInput.files, !tscInput.ignoreCase, cwd)
+ sys.defaultLibraryPath = libPath
+ sys.currentWrite = currentWrite
+ sys.tracer = harnessutil.NewTracerForBaselining(tspath.ComparePathsOptions{
+ UseCaseSensitiveFileNames: !tscInput.ignoreCase,
+ CurrentDirectory: cwd,
+ }, currentWrite)
+ sys.env = tscInput.env
+ sys.forIncrementalCorrectness = forIncrementalCorrectness
// Ensure the default library file is present
sys.ensureLibPathExists("lib.d.ts")
@@ -126,11 +139,12 @@ type snapshot struct {
}
type testSys struct {
- currentWrite *strings.Builder
- tracer *harnessutil.TracerForBaselining
- serializedDiff *snapshot
+ currentWrite *strings.Builder
+ tracer *harnessutil.TracerForBaselining
+ serializedDiff *snapshot
+ forIncrementalCorrectness bool
- fs *incrementaltestutil.FsHandlingBuildInfo
+ fs *testFs
defaultLibraryPath string
cwd string
env map[string]string
@@ -138,8 +152,8 @@ type testSys struct {
}
var (
- _ execute.System = (*testSys)(nil)
- _ execute.CommandLineTesting = (*testSys)(nil)
+ _ tsc.System = (*testSys)(nil)
+ _ tsc.CommandLineTesting = (*testSys)(nil)
)
func (s *testSys) Now() time.Time {
@@ -154,12 +168,8 @@ func (s *testSys) FS() vfs.FS {
return s.fs
}
-func (s *testSys) testFs() *testFs {
- return s.fs.FS.(*testFs)
-}
-
func (s *testSys) fsFromFileMap() iovfs.FsWithSys {
- return s.testFs().FS.(iovfs.FsWithSys)
+ return s.fs.FS.(iovfs.FsWithSys)
}
func (s *testSys) mapFs() *vfstest.MapFS {
@@ -169,10 +179,10 @@ func (s *testSys) mapFs() *vfstest.MapFS {
func (s *testSys) ensureLibPathExists(path string) {
path = s.defaultLibraryPath + "/" + path
if _, ok := s.fsFromFileMap().ReadFile(path); !ok {
- if s.testFs().defaultLibs == nil {
- s.testFs().defaultLibs = &collections.SyncSet[string]{}
+ if s.fs.defaultLibs == nil {
+ s.fs.defaultLibs = &collections.SyncSet[string]{}
}
- s.testFs().defaultLibs.Add(path)
+ s.fs.defaultLibs.Add(path)
err := s.fsFromFileMap().WriteFile(path, tscDefaultLibContent, false)
if err != nil {
panic("Failed to write default library file: " + err.Error())
@@ -207,34 +217,65 @@ func (s *testSys) GetEnvironmentVariable(name string) string {
return s.env[name]
}
-func (s *testSys) OnListFilesStart() {
- fmt.Fprintln(s.Writer(), listFileStart)
+func (s *testSys) OnEmittedFiles(result *compiler.EmitResult) {
+ if result != nil {
+ for _, file := range result.EmittedFiles {
+ // Ensure that the timestamp for emitted files is in the order
+ now := s.Now()
+ if err := s.fsFromFileMap().Chtimes(file, time.Time{}, now); err != nil {
+ panic("Failed to change time for emitted file: " + file + ": " + err.Error())
+ }
+ }
+ }
+}
+
+func (s *testSys) OnListFilesStart(w io.Writer) {
+ fmt.Fprintln(w, listFileStart)
}
-func (s *testSys) OnListFilesEnd() {
- fmt.Fprintln(s.Writer(), listFileEnd)
+func (s *testSys) OnListFilesEnd(w io.Writer) {
+ fmt.Fprintln(w, listFileEnd)
}
-func (s *testSys) OnStatisticsStart() {
- fmt.Fprintln(s.Writer(), statisticsStart)
+func (s *testSys) OnStatisticsStart(w io.Writer) {
+ fmt.Fprintln(w, statisticsStart)
}
-func (s *testSys) OnStatisticsEnd() {
- fmt.Fprintln(s.Writer(), statisticsEnd)
+func (s *testSys) OnStatisticsEnd(w io.Writer) {
+ fmt.Fprintln(w, statisticsEnd)
}
-func (s *testSys) GetTrace() func(str string) {
+func (s *testSys) OnBuildStatusReportStart(w io.Writer) {
+ fmt.Fprintln(w, buildStatusReportStart)
+}
+
+func (s *testSys) OnBuildStatusReportEnd(w io.Writer) {
+ fmt.Fprintln(w, buildStatusReportEnd)
+}
+
+func (s *testSys) GetTrace(w io.Writer) func(str string) {
return func(str string) {
- fmt.Fprintln(s.currentWrite, traceStart)
- defer fmt.Fprintln(s.currentWrite, traceEnd)
- s.tracer.Trace(str)
+ fmt.Fprintln(w, traceStart)
+ defer fmt.Fprintln(w, traceEnd)
+ // With tsc -b building projects in parallel we cannot serialize the package.json lookup trace
+ // so trace as if it wasnt cached
+ s.tracer.TraceWithWriter(w, str, w == s.Writer())
}
}
-func (s *testSys) baselineProgram(baseline *strings.Builder, program *incremental.Program, watcher *execute.Watcher) {
+func (s *testSys) baselinePrograms(baseline *strings.Builder, programs []*incremental.Program, watcher tsc.Watcher) {
if watcher != nil {
- program = watcher.GetProgram()
+ programs = []*incremental.Program{watcher.GetProgram()}
+ }
+ for index, program := range programs {
+ if index > 0 {
+ baseline.WriteString("\n")
+ }
+ s.baselineProgram(baseline, program)
}
+}
+
+func (s *testSys) baselineProgram(baseline *strings.Builder, program *incremental.Program) {
if program == nil {
return
}
@@ -288,14 +329,16 @@ var (
fakeTimeStamp = "HH:MM:SS AM"
fakeDuration = "d.ddds"
- buildStartingAt = "build starting at "
- buildFinishedIn = "build finished in "
- listFileStart = "!!! List files start"
- listFileEnd = "!!! List files end"
- statisticsStart = "!!! Statistics start"
- statisticsEnd = "!!! Statistics end"
- traceStart = "!!! Trace start"
- traceEnd = "!!! Trace end"
+ buildStartingAt = "build starting at "
+ buildFinishedIn = "build finished in "
+ listFileStart = "!!! List files start"
+ listFileEnd = "!!! List files end"
+ statisticsStart = "!!! Statistics start"
+ statisticsEnd = "!!! Statistics end"
+ buildStatusReportStart = "!!! Build Status Report Start"
+ buildStatusReportEnd = "!!! Build Status Report End"
+ traceStart = "!!! Trace start"
+ traceEnd = "!!! Trace end"
)
func (s *testSys) baselineOutput(baseline io.Writer) {
@@ -312,16 +355,27 @@ type outputSanitizer struct {
}
func (o *outputSanitizer) addOutputLine(s string) {
+ if change := strings.ReplaceAll(s, fmt.Sprintf("'%s'", core.Version()), fmt.Sprintf("'%s'", harnessutil.FakeTSVersion)); change != s {
+ s = change
+ }
+ if change := strings.ReplaceAll(s, "Version "+core.Version(), "Version "+harnessutil.FakeTSVersion); change != s {
+ s = change
+ }
o.outputLines = append(o.outputLines, s)
}
+func (o *outputSanitizer) sanitizeBuildStatusTimeStamp() string {
+ statusLine := o.lines[o.index]
+ hhSeparator := strings.IndexRune(statusLine, ':')
+ if hhSeparator < 2 {
+ panic("Expected timestamp")
+ }
+ return statusLine[:hhSeparator-2] + fakeTimeStamp + statusLine[hhSeparator+len(fakeTimeStamp)-2:]
+}
+
func (o *outputSanitizer) transformLines() string {
for ; o.index < len(o.lines); o.index++ {
line := o.lines[o.index]
- if change := strings.Replace(line, "Version "+core.Version(), "Version "+harnessutil.FakeTSVersion, 1); change != line {
- o.addOutputLine(change)
- continue
- }
if strings.HasPrefix(line, buildStartingAt) {
if !o.forComparing {
o.addOutputLine(buildStartingAt + fakeTimeStamp)
@@ -334,9 +388,10 @@ func (o *outputSanitizer) transformLines() string {
}
continue
}
- if !o.addOrSkipLinesForComparing(listFileStart, listFileEnd, false) &&
- !o.addOrSkipLinesForComparing(statisticsStart, statisticsEnd, true) &&
- !o.addOrSkipLinesForComparing(traceStart, traceEnd, false) {
+ if !o.addOrSkipLinesForComparing(listFileStart, listFileEnd, false, nil) &&
+ !o.addOrSkipLinesForComparing(statisticsStart, statisticsEnd, true, nil) &&
+ !o.addOrSkipLinesForComparing(traceStart, traceEnd, false, nil) &&
+ !o.addOrSkipLinesForComparing(buildStatusReportStart, buildStatusReportEnd, false, o.sanitizeBuildStatusTimeStamp) {
o.addOutputLine(line)
}
}
@@ -347,17 +402,24 @@ func (o *outputSanitizer) addOrSkipLinesForComparing(
lineStart string,
lineEnd string,
skipEvenIfNotComparing bool,
+ sanitizeFirstLine func() string,
) bool {
if o.lines[o.index] != lineStart {
return false
}
o.index++
+ isFirstLine := true
for ; o.index < len(o.lines); o.index++ {
if o.lines[o.index] == lineEnd {
return true
}
if !o.forComparing && !skipEvenIfNotComparing {
- o.addOutputLine(o.lines[o.index])
+ line := o.lines[o.index]
+ if isFirstLine && sanitizeFirstLine != nil {
+ line = sanitizeFirstLine()
+ isFirstLine = false
+ }
+ o.addOutputLine(line)
}
}
panic("Expected lineEnd" + lineEnd + " not found after " + lineStart)
@@ -382,7 +444,6 @@ func (s *testSys) baselineFSwithDiff(baseline io.Writer) {
// todo: baselines the entire fs, possibly doesn't correctly diff all cases of emitted files, since emit isn't fully implemented and doesn't always emit the same way as strada
snap := map[string]*diffEntry{}
- testFs := s.testFs()
diffs := map[string]string{}
for path, file := range s.mapFs().Entries() {
@@ -396,7 +457,7 @@ func (s *testSys) baselineFSwithDiff(baseline io.Writer) {
s.addFsEntryDiff(diffs, newEntry, path)
continue
} else if file.Mode.IsRegular() {
- newEntry := &diffEntry{content: string(file.Data), mTime: file.ModTime, isWritten: testFs.writtenFiles.Has(path)}
+ newEntry := &diffEntry{content: string(file.Data), mTime: file.ModTime, isWritten: s.fs.writtenFiles.Has(path)}
snap[path] = newEntry
s.addFsEntryDiff(diffs, newEntry, path)
}
@@ -411,8 +472,8 @@ func (s *testSys) baselineFSwithDiff(baseline io.Writer) {
}
}
var defaultLibs collections.SyncSet[string]
- if s.testFs().defaultLibs != nil {
- s.testFs().defaultLibs.Range(func(libPath string) bool {
+ if s.fs.defaultLibs != nil {
+ s.fs.defaultLibs.Range(func(libPath string) bool {
defaultLibs.Add(libPath)
return true
})
@@ -427,7 +488,7 @@ func (s *testSys) baselineFSwithDiff(baseline io.Writer) {
fmt.Fprint(baseline, "//// ["+path+"] ", diffs[path], "\n")
}
fmt.Fprintln(baseline)
- testFs.writtenFiles = collections.SyncSet[string]{} // Reset written files after baseline
+ s.fs.writtenFiles = collections.SyncSet[string]{} // Reset written files after baseline
}
func (s *testSys) addFsEntryDiff(diffs map[string]string, newDirContent *diffEntry, path string) {
@@ -439,7 +500,7 @@ func (s *testSys) addFsEntryDiff(diffs map[string]string, newDirContent *diffEnt
}
// todo handle more cases of fs changes
if oldDirContent == nil {
- if s.testFs().defaultLibs == nil || !s.testFs().defaultLibs.Has(path) {
+ if s.fs.defaultLibs == nil || !s.fs.defaultLibs.Has(path) {
if newDirContent.symlinkTarget != "" {
diffs[path] = "-> " + newDirContent.symlinkTarget + " *new*"
} else {
@@ -454,7 +515,7 @@ func (s *testSys) addFsEntryDiff(diffs map[string]string, newDirContent *diffEnt
diffs[path] = "*rewrite with same content*"
} else if newDirContent.mTime != oldDirContent.mTime {
diffs[path] = "*mTime changed*"
- } else if defaultLibs != nil && defaultLibs.Has(path) && s.testFs().defaultLibs != nil && !s.testFs().defaultLibs.Has(path) {
+ } else if defaultLibs != nil && defaultLibs.Has(path) && s.fs.defaultLibs != nil && !s.fs.defaultLibs.Has(path) {
// Lib file that was read
diffs[path] = "*Lib*\n" + newDirContent.content
}
@@ -466,6 +527,12 @@ func (s *testSys) writeFileNoError(path string, content string, writeByteOrderMa
}
}
+func (s *testSys) removeNoError(path string) {
+ if err := s.fsFromFileMap().Remove(path); err != nil {
+ panic(err)
+ }
+}
+
func (s *testSys) replaceFileText(path string, oldText string, newText string) {
content, ok := s.fsFromFileMap().ReadFile(path)
if !ok {
diff --git a/internal/execute/tsctests/tsc_test.go b/internal/execute/tsctests/tsc_test.go
new file mode 100644
index 0000000000..81eb372253
--- /dev/null
+++ b/internal/execute/tsctests/tsc_test.go
@@ -0,0 +1,3546 @@
+package tsctests
+
+import (
+ "fmt"
+ "slices"
+ "strings"
+ "testing"
+
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
+ "github.com/microsoft/typescript-go/internal/vfs/vfstest"
+)
+
+func TestTscCommandline(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped",
+ env: map[string]string{
+ "TS_TEST_TERMINAL_WIDTH": "120",
+ },
+ commandLineArgs: nil,
+ },
+ {
+ subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped when host cannot provide terminal width",
+ commandLineArgs: nil,
+ },
+ {
+ subScenario: "does not add color when NO_COLOR is set",
+ env: map[string]string{
+ "NO_COLOR": "true",
+ },
+ commandLineArgs: nil,
+ },
+ {
+ subScenario: "when build not first argument",
+ commandLineArgs: []string{"--verbose", "--build"},
+ },
+ {
+ subScenario: "help",
+ commandLineArgs: []string{"--help"},
+ },
+ {
+ subScenario: "help all",
+ commandLineArgs: []string{"--help", "--all"},
+ },
+ {
+ subScenario: "Parse --lib option with file name",
+ files: FileMap{"/home/src/workspaces/project/first.ts": `export const Key = Symbol()`},
+ commandLineArgs: []string{"--lib", "es6 ", "first.ts"},
+ },
+ {
+ subScenario: "Project is empty string",
+ files: FileMap{
+ "/home/src/workspaces/project/first.ts": `export const a = 1`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "strict": true,
+ "noEmit": true
+ }
+ }`),
+ },
+ commandLineArgs: []string{},
+ },
+ {
+ subScenario: "Parse -p",
+ files: FileMap{
+ "/home/src/workspaces/project/first.ts": `export const a = 1`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "strict": true,
+ "noEmit": true
+ }
+ }`),
+ },
+ commandLineArgs: []string{"-p", "."},
+ },
+ {
+ subScenario: "Parse -p with path to tsconfig file",
+ files: FileMap{
+ "/home/src/workspaces/project/first.ts": `export const a = 1`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "strict": true,
+ "noEmit": true
+ }
+ }`),
+ },
+ commandLineArgs: []string{"-p", "/home/src/workspaces/project/tsconfig.json"},
+ },
+ {
+ subScenario: "Parse -p with path to tsconfig folder",
+ files: FileMap{
+ "/home/src/workspaces/project/first.ts": `export const a = 1`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "strict": true,
+ "noEmit": true
+ }
+ }`),
+ },
+ commandLineArgs: []string{"-p", "/home/src/workspaces/project"},
+ },
+ {
+ subScenario: "Parse enum type options",
+ commandLineArgs: []string{"--moduleResolution", "nodenext ", "first.ts", "--module", "nodenext", "--target", "esnext", "--moduleDetection", "auto", "--jsx", "react", "--newLine", "crlf"},
+ },
+ {
+ subScenario: "Parse watch interval option",
+ files: FileMap{
+ "/home/src/workspaces/project/first.ts": `export const a = 1`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "strict": true,
+ "noEmit": true
+ }
+ }`),
+ },
+ commandLineArgs: []string{"-w", "--watchInterval", "1000"},
+ },
+ {
+ subScenario: "Parse watch interval option without tsconfig.json",
+ commandLineArgs: []string{"-w", "--watchInterval", "1000"},
+ },
+ {
+ subScenario: "Config with references and empty file and refers to config with noEmit",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`{
+ "files": [],
+ "references": [
+ {
+ "path": "./packages/pkg1"
+ },
+ ],
+ }`),
+ "/home/src/workspaces/project/packages/pkg1/tsconfig.json": stringtestutil.Dedent(`{
+ "compilerOptions": {
+ "composite": true,
+ "noEmit": true
+ },
+ "files": [
+ "./index.ts",
+ ],
+ }`),
+ "/home/src/workspaces/project/packages/pkg1/index.ts": `export const a = 1;`,
+ },
+ commandLineArgs: []string{"-p", "."},
+ },
+ }
+
+ for _, testCase := range testCases {
+ testCase.run(t, "commandLine")
+ }
+}
+
+func TestTscComposite(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "when setting composite false on command line",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "composite": true,
+ },
+ "include": [
+ "src/**/*.ts",
+ ],
+ }`),
+ },
+ commandLineArgs: []string{"--composite", "false"},
+ },
+ {
+ // !!! sheetal null is not reflected in final options
+ subScenario: "when setting composite null on command line",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "composite": true,
+ },
+ "include": [
+ "src/**/*.ts",
+ ],
+ }`),
+ },
+ commandLineArgs: []string{"--composite", "null"},
+ },
+ {
+ subScenario: "when setting composite false on command line but has tsbuild info in config",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "composite": true,
+ "tsBuildInfoFile": "tsconfig.json.tsbuildinfo",
+ },
+ "include": [
+ "src/**/*.ts",
+ ],
+ }`),
+ },
+ commandLineArgs: []string{"--composite", "false"},
+ },
+ {
+ subScenario: "when setting composite false and tsbuildinfo as null on command line but has tsbuild info in config",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "composite": true,
+ "tsBuildInfoFile": "tsconfig.json.tsbuildinfo",
+ },
+ "include": [
+ "src/**/*.ts",
+ ],
+ }`),
+ },
+ commandLineArgs: []string{"--composite", "false", "--tsBuildInfoFile", "null"},
+ },
+ {
+ subScenario: "converting to modules",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "none",
+ "composite": true,
+ },
+ }`),
+ },
+ edits: []*tscEdit{
+ {
+ caption: "convert to modules",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", "none", "es2015")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "synthetic jsx import of ESM module from CJS module no crash no jsx element",
+ files: FileMap{
+ "/home/src/projects/project/src/main.ts": "export default 42;",
+ "/home/src/projects/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "module": "Node16",
+ "jsx": "react-jsx",
+ "jsxImportSource": "solid-js",
+ },
+ }`),
+ "/home/src/projects/project/node_modules/solid-js/package.json": stringtestutil.Dedent(`
+ {
+ "name": "solid-js",
+ "type": "module"
+ }
+ `),
+ "/home/src/projects/project/node_modules/solid-js/jsx-runtime.d.ts": stringtestutil.Dedent(`
+ export namespace JSX {
+ type IntrinsicElements = { div: {}; };
+ }
+ `),
+ },
+ cwd: "/home/src/projects/project",
+ },
+ {
+ subScenario: "synthetic jsx import of ESM module from CJS module error on jsx element",
+ files: FileMap{
+ "/home/src/projects/project/src/main.tsx": "export default ;",
+ "/home/src/projects/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "module": "Node16",
+ "jsx": "react-jsx",
+ "jsxImportSource": "solid-js",
+ },
+ }`),
+ "/home/src/projects/project/node_modules/solid-js/package.json": stringtestutil.Dedent(`
+ {
+ "name": "solid-js",
+ "type": "module"
+ }
+ `),
+ "/home/src/projects/project/node_modules/solid-js/jsx-runtime.d.ts": stringtestutil.Dedent(`
+ export namespace JSX {
+ type IntrinsicElements = { div: {}; };
+ }
+ `),
+ },
+ cwd: "/home/src/projects/project",
+ },
+ }
+
+ for _, testCase := range testCases {
+ testCase.run(t, "composite")
+ }
+}
+
+func TestTscDeclarationEmit(t *testing.T) {
+ t.Parallel()
+ getBuildDeclarationEmitDtsReferenceAsTrippleSlashMap := func(useNoRef bool) FileMap {
+ files := FileMap{
+ "/home/src/workspaces/solution/tsconfig.base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "rootDir": "./",
+ "outDir": "lib",
+ },
+ }`),
+ "/home/src/workspaces/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "references": [{ "path": "./src" }],
+ "include": [],
+ }`),
+ "/home/src/workspaces/solution/src/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "references": [{ "path": "./subProject" }, { "path": "./subProject2" }],
+ "include": [],
+ }`),
+ "/home/src/workspaces/solution/src/subProject/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": { "composite": true },
+ "references": [{ "path": "../common" }],
+ "include": ["./index.ts"],
+ }`),
+ "/home/src/workspaces/solution/src/subProject/index.ts": stringtestutil.Dedent(`
+ import { Nominal } from '../common/nominal';
+ export type MyNominal = Nominal;`),
+ "/home/src/workspaces/solution/src/subProject2/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": { "composite": true },
+ "references": [{ "path": "../subProject" }],
+ "include": ["./index.ts"],
+ }`),
+ "/home/src/workspaces/solution/src/subProject2/index.ts": stringtestutil.Dedent(`
+ import { MyNominal } from '../subProject/index';
+ const variable = {
+ key: 'value' as MyNominal,
+ };
+ export function getVar(): keyof typeof variable {
+ return 'key';
+ }`),
+ "/home/src/workspaces/solution/src/common/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": { "composite": true },
+ "include": ["./nominal.ts"],
+ }`),
+ "/home/src/workspaces/solution/src/common/nominal.ts": stringtestutil.Dedent(`
+ ///
+ export declare type Nominal = MyNominal;`),
+ "/home/src/workspaces/solution/src/common/types.d.ts": stringtestutil.Dedent(`
+ declare type MyNominal = T & {
+ specialKey: Name;
+ };`),
+ }
+ if useNoRef {
+ files["/home/src/workspaces/solution/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "extends": "./tsconfig.base.json",
+ "compilerOptions": { "composite": true },
+ "include": ["./src/**/*.ts"],
+ }`)
+ }
+ return files
+ }
+
+ getTscDeclarationEmitDtsErrorsFileMap := func(composite bool, incremental bool) FileMap {
+ return FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "composite": %t,
+ "incremental": %t,
+ "declaration": true,
+ "skipLibCheck": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`, composite, incremental)),
+ "/home/src/workspaces/project/index.ts": stringtestutil.Dedent(`
+ import ky from 'ky';
+ export const api = ky.extend({});
+ `),
+ "/home/src/workspaces/project/package.json": stringtestutil.Dedent(`
+ {
+ "type": "module"
+ }`),
+ "/home/src/workspaces/project/node_modules/ky/distribution/index.d.ts": stringtestutil.Dedent(`
+ type KyInstance = {
+ extend(options: Record): KyInstance;
+ }
+ declare const ky: KyInstance;
+ export default ky;
+ `),
+ "/home/src/workspaces/project/node_modules/ky/package.json": stringtestutil.Dedent(`
+ {
+ "name": "ky",
+ "type": "module",
+ "main": "./distribution/index.js"
+ }
+ `),
+ }
+ }
+
+ pluginOneConfig := func() string {
+ return stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "declaration": true,
+ "traceResolution": true,
+ },
+ }`)
+ }
+
+ pluginOneIndex := func() string {
+ return `import pluginTwo from "plugin-two"; // include this to add reference to symlink`
+ }
+
+ pluginOneAction := func() string {
+ return stringtestutil.Dedent(`
+ import { actionCreatorFactory } from "typescript-fsa"; // Include version of shared lib
+ const action = actionCreatorFactory("somekey");
+ const featureOne = action<{ route: string }>("feature-one");
+ export const actions = { featureOne };`)
+ }
+
+ pluginTwoDts := func() string {
+ return stringtestutil.Dedent(`
+ declare const _default: {
+ features: {
+ featureOne: {
+ actions: {
+ featureOne: {
+ (payload: {
+ name: string;
+ order: number;
+ }, meta?: {
+ [key: string]: any;
+ }): import("typescript-fsa").Action<{
+ name: string;
+ order: number;
+ }>;
+ };
+ };
+ path: string;
+ };
+ };
+ };
+ export default _default;`)
+ }
+
+ fsaPackageJson := func() string {
+ return stringtestutil.Dedent(`
+ {
+ "name": "typescript-fsa",
+ "version": "3.0.0-beta-2"
+ }`)
+ }
+
+ fsaIndex := func() string {
+ return stringtestutil.Dedent(`
+ export interface Action {
+ type: string;
+ payload: Payload;
+ }
+ export declare type ActionCreator = {
+ type: string;
+ (payload: Payload): Action;
+ }
+ export interface ActionCreatorFactory {
+ (type: string): ActionCreator;
+ }
+ export declare function actionCreatorFactory(prefix?: string | null): ActionCreatorFactory;
+ export default actionCreatorFactory;`)
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "when declaration file is referenced through triple slash",
+ files: getBuildDeclarationEmitDtsReferenceAsTrippleSlashMap(false),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "--verbose"},
+ },
+ {
+ subScenario: "when declaration file is referenced through triple slash but uses no references",
+ files: getBuildDeclarationEmitDtsReferenceAsTrippleSlashMap(true),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "--verbose"},
+ },
+ {
+ subScenario: "when declaration file used inferred type from referenced project",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "paths": { "@fluentui/*": ["./packages/*/src"] },
+ },
+ }`),
+ "/home/src/workspaces/project/packages/pkg1/src/index.ts": stringtestutil.Dedent(`
+ export interface IThing {
+ a: string;
+ }
+ export interface IThings {
+ thing1: IThing;
+ }
+ `),
+ "/home/src/workspaces/project/packages/pkg1/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig",
+ "compilerOptions": { "outDir": "lib" },
+ "include": ["src"],
+ }
+ `),
+ "/home/src/workspaces/project/packages/pkg2/src/index.ts": stringtestutil.Dedent(`
+ import { IThings } from '@fluentui/pkg1';
+ export function fn4() {
+ const a: IThings = { thing1: { a: 'b' } };
+ return a.thing1;
+ }
+ `),
+ "/home/src/workspaces/project/packages/pkg2/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig",
+ "compilerOptions": { "outDir": "lib" },
+ "include": ["src"],
+ "references": [{ "path": "../pkg1" }],
+ }
+ `),
+ },
+ commandLineArgs: []string{"--b", "packages/pkg2/tsconfig.json", "--verbose"},
+ },
+ {
+ subScenario: "reports dts generation errors",
+ files: getTscDeclarationEmitDtsErrorsFileMap(false, false),
+ commandLineArgs: []string{"-b", "--explainFiles", "--listEmittedFiles", "--v"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "reports dts generation errors with incremental",
+ files: getTscDeclarationEmitDtsErrorsFileMap(false, true),
+ commandLineArgs: []string{"-b", "--explainFiles", "--listEmittedFiles", "--v"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "reports dts generation errors",
+ files: getTscDeclarationEmitDtsErrorsFileMap(false, false),
+ commandLineArgs: []string{"--explainFiles", "--listEmittedFiles"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "build -b",
+ commandLineArgs: []string{"-b", "--explainFiles", "--listEmittedFiles", "--v"},
+ },
+ },
+ },
+ {
+ subScenario: "reports dts generation errors with incremental",
+ files: getTscDeclarationEmitDtsErrorsFileMap(true, true),
+ commandLineArgs: []string{"--explainFiles", "--listEmittedFiles"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "build -b",
+ commandLineArgs: []string{"-b", "--explainFiles", "--listEmittedFiles", "--v"},
+ },
+ },
+ },
+ {
+ subScenario: "when using Windows paths and uppercase letters",
+ files: FileMap{
+ "D:/Work/pkg1/package.json": stringtestutil.Dedent(`
+ {
+ "name": "ts-specifier-bug",
+ "version": "1.0.0",
+ "main": "index.js"
+ }`),
+ "D:/Work/pkg1/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "declaration": true,
+ "target": "es2017",
+ "outDir": "./dist",
+ },
+ "include": ["src"],
+ }`),
+ "D:/Work/pkg1/src/main.ts": stringtestutil.Dedent(`
+ import { PartialType } from './utils';
+
+ class Common {}
+
+ export class Sub extends PartialType(Common) {
+ id: string;
+ }
+ `),
+ "D:/Work/pkg1/src/utils/index.ts": stringtestutil.Dedent(`
+ import { MyType, MyReturnType } from './type-helpers';
+
+ export function PartialType(classRef: MyType) {
+ abstract class PartialClassType {
+ constructor() {}
+ }
+
+ return PartialClassType as MyReturnType;
+ }
+ `),
+ "D:/Work/pkg1/src/utils/type-helpers.ts": stringtestutil.Dedent(`
+ export type MyReturnType = {
+ new (...args: any[]): any;
+ };
+
+ export interface MyType extends Function {
+ new (...args: any[]): T;
+ }
+ `),
+ },
+ cwd: "D:/Work/pkg1",
+ windowsStyleRoot: "D:/",
+ ignoreCase: true,
+ commandLineArgs: []string{"-p", "D:\\Work\\pkg1", "--explainFiles"},
+ },
+ {
+ // !!! sheetal redirected files not yet implemented
+ subScenario: "when same version is referenced through source and another symlinked package",
+ files: FileMap{
+ `/user/username/projects/myproject/plugin-two/index.d.ts`: pluginTwoDts(),
+ `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/package.json`: fsaPackageJson(),
+ `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/index.d.ts`: fsaIndex(),
+ `/user/username/projects/myproject/plugin-one/tsconfig.json`: pluginOneConfig(),
+ `/user/username/projects/myproject/plugin-one/index.ts`: pluginOneIndex(),
+ `/user/username/projects/myproject/plugin-one/action.ts`: pluginOneAction(),
+ `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/package.json`: fsaPackageJson(),
+ `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`: fsaIndex(),
+ `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`: vfstest.Symlink(`/user/username/projects/myproject/plugin-two`),
+ },
+ cwd: "/user/username/projects/myproject",
+ commandLineArgs: []string{"-p", "plugin-one", "--explainFiles"},
+ },
+ {
+ // !!! sheetal redirected files not yet implemented
+ subScenario: "when same version is referenced through source and another symlinked package with indirect link",
+ files: FileMap{
+ `/user/username/projects/myproject/plugin-two/package.json`: stringtestutil.Dedent(`
+ {
+ "name": "plugin-two",
+ "version": "0.1.3",
+ "main": "dist/commonjs/index.js"
+ }`),
+ `/user/username/projects/myproject/plugin-two/dist/commonjs/index.d.ts`: pluginTwoDts(),
+ `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/package.json`: fsaPackageJson(),
+ `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/index.d.ts`: fsaIndex(),
+ `/user/username/projects/myproject/plugin-one/tsconfig.json`: pluginOneConfig(),
+ `/user/username/projects/myproject/plugin-one/index.ts`: pluginOneIndex() + "\n" + pluginOneAction(),
+ `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/package.json`: fsaPackageJson(),
+ `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`: fsaIndex(),
+ `/temp/yarn/data/link/plugin-two`: vfstest.Symlink(`/user/username/projects/myproject/plugin-two`),
+ `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`: vfstest.Symlink(`/temp/yarn/data/link/plugin-two`),
+ },
+ cwd: "/user/username/projects/myproject",
+ commandLineArgs: []string{"-p", "plugin-one", "--explainFiles"},
+ },
+ {
+ // !!! sheetal strada has error for d.ts generation in pkg3/src/keys.ts but corsa doesnt have that
+ subScenario: "when pkg references sibling package through indirect symlink",
+ files: FileMap{
+ `/user/username/projects/myproject/pkg1/dist/index.d.ts`: `export * from './types';`,
+ `/user/username/projects/myproject/pkg1/dist/types.d.ts`: stringtestutil.Dedent(`
+ export declare type A = {
+ id: string;
+ };
+ export declare type B = {
+ id: number;
+ };
+ export declare type IdType = A | B;
+ export declare class MetadataAccessor {
+ readonly key: string;
+ private constructor();
+ toString(): string;
+ static create(key: string): MetadataAccessor;
+ }`),
+ `/user/username/projects/myproject/pkg1/package.json`: stringtestutil.Dedent(`
+ {
+ "name": "@raymondfeng/pkg1",
+ "version": "1.0.0",
+ "main": "dist/index.js",
+ "typings": "dist/index.d.ts"
+ }`),
+ `/user/username/projects/myproject/pkg2/dist/index.d.ts`: `export * from './types';`,
+ `/user/username/projects/myproject/pkg2/dist/types.d.ts`: `export {MetadataAccessor} from '@raymondfeng/pkg1';`,
+ `/user/username/projects/myproject/pkg2/package.json`: stringtestutil.Dedent(`
+ {
+ "name": "@raymondfeng/pkg2",
+ "version": "1.0.0",
+ "main": "dist/index.js",
+ "typings": "dist/index.d.ts"
+ }`),
+ `/user/username/projects/myproject/pkg3/src/index.ts`: `export * from './keys';`,
+ `/user/username/projects/myproject/pkg3/src/keys.ts`: stringtestutil.Dedent(`
+ import {MetadataAccessor} from "@raymondfeng/pkg2";
+ export const ADMIN = MetadataAccessor.create('1');`),
+ `/user/username/projects/myproject/pkg3/tsconfig.json`: stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src",
+ "target": "es5",
+ "module": "commonjs",
+ "strict": true,
+ "esModuleInterop": true,
+ "declaration": true,
+ },
+ }`),
+ `/user/username/projects/myproject/pkg2/node_modules/@raymondfeng/pkg1`: vfstest.Symlink(`/user/username/projects/myproject/pkg1`),
+ `/user/username/projects/myproject/pkg3/node_modules/@raymondfeng/pkg2`: vfstest.Symlink(`/user/username/projects/myproject/pkg2`),
+ },
+ cwd: "/user/username/projects/myproject",
+ commandLineArgs: []string{"-p", "pkg3", "--explainFiles"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "declarationEmit")
+ }
+}
+
+func TestTscExtends(t *testing.T) {
+ t.Parallel()
+ getBuildConfigFileExtendsFileMap := func() FileMap {
+ return FileMap{
+ "/home/src/workspaces/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "./shared/tsconfig.json" },
+ { "path": "./webpack/tsconfig.json" },
+ ],
+ "files": [],
+ }`),
+ "/home/src/workspaces/solution/shared/tsconfig-base.json": stringtestutil.Dedent(`
+ {
+ "include": ["./typings-base/"],
+ }`),
+ "/home/src/workspaces/solution/shared/typings-base/globals.d.ts": `type Unrestricted = any;`,
+ "/home/src/workspaces/solution/shared/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "./tsconfig-base.json",
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "../target-tsc-build/",
+ "rootDir": "..",
+ },
+ "files": ["./index.ts"],
+ }`),
+ "/home/src/workspaces/solution/shared/index.ts": `export const a: Unrestricted = 1;`,
+ "/home/src/workspaces/solution/webpack/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../shared/tsconfig-base.json",
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "../target-tsc-build/",
+ "rootDir": "..",
+ },
+ "files": ["./index.ts"],
+ "references": [{ "path": "../shared/tsconfig.json" }],
+ }`),
+ "/home/src/workspaces/solution/webpack/index.ts": `export const b: Unrestricted = 1;`,
+ }
+ }
+ getTscExtendsWithSymlinkTestCase := func(builtType string) *tscInput {
+ return &tscInput{
+ subScenario: "resolves the symlink path",
+ files: FileMap{
+ "/users/user/projects/myconfigs/node_modules/@something/tsconfig-node/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "@something/tsconfig-base/tsconfig.json",
+ "compilerOptions": {
+ "removeComments": true
+ }
+ }
+ `),
+ "/users/user/projects/myconfigs/node_modules/@something/tsconfig-base/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true }
+ }
+ `),
+ "/users/user/projects/myproject/src/index.ts": stringtestutil.Dedent(`
+ // some comment
+ export const x = 10;
+ `),
+ "/users/user/projects/myproject/src/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "@something/tsconfig-node/tsconfig.json"
+ }`),
+ "/users/user/projects/myproject/node_modules/@something/tsconfig-node": vfstest.Symlink("/users/user/projects/myconfigs/node_modules/@something/tsconfig-node"),
+ },
+ cwd: "/users/user/projects/myproject",
+ commandLineArgs: []string{builtType, "src", "--extendedDiagnostics"},
+ }
+ }
+ getTscExtendsConfigDirTestCase := func(subScenarioSufix string, commandLineArgs []string) *tscInput {
+ return &tscInput{
+ subScenario: "configDir template" + subScenarioSufix,
+ files: FileMap{
+ "/home/src/projects/configs/first/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../second/tsconfig.json",
+ "include": ["${configDir}/src"],
+ "compilerOptions": {
+ "typeRoots": ["root1", "${configDir}/root2", "root3"],
+ "types": [],
+ },
+ }`),
+ "/home/src/projects/configs/second/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "files": ["${configDir}/main.ts"],
+ "compilerOptions": {
+ "declarationDir": "${configDir}/decls",
+ "paths": {
+ "@myscope/*": ["${configDir}/types/*"],
+ },
+ },
+ "watchOptions": {
+ "excludeFiles": ["${configDir}/main.ts"],
+ },
+ }`),
+ "/home/src/projects/myproject/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../configs/first/tsconfig.json",
+ "compilerOptions": {
+ "declaration": true,
+ "outDir": "outDir",
+ "traceResolution": true,
+ },
+ }`),
+ "/home/src/projects/myproject/main.ts": stringtestutil.Dedent(`
+ // some comment
+ export const y = 10;
+ import { x } from "@myscope/sometype";
+ `),
+ "/home/src/projects/myproject/types/sometype.ts": stringtestutil.Dedent(`
+ export const x = 10;
+ `),
+ },
+ cwd: "/home/src/projects/myproject",
+ commandLineArgs: commandLineArgs,
+ }
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "when building solution with projects extends config with include",
+ files: getBuildConfigFileExtendsFileMap(),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "--v", "--listFiles"},
+ },
+ {
+ subScenario: "when building project uses reference and both extend config with include",
+ files: getBuildConfigFileExtendsFileMap(),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "webpack/tsconfig.json", "--v", "--listFiles"},
+ },
+ getTscExtendsWithSymlinkTestCase("-p"),
+ getTscExtendsWithSymlinkTestCase("-b"),
+ getTscExtendsConfigDirTestCase("", []string{"--explainFiles"}),
+ getTscExtendsConfigDirTestCase(" showConfig", []string{"--showConfig"}),
+ getTscExtendsConfigDirTestCase(" with commandline", []string{"--explainFiles", "--outDir", "${configDir}/outDir"}),
+ getTscExtendsConfigDirTestCase("", []string{"--b", "--explainFiles", "--v"}),
+ }
+
+ for _, test := range testCases {
+ test.run(t, "extends")
+ }
+}
+
+func TestTscIncremental(t *testing.T) {
+ t.Parallel()
+ getConstEnumTest := func(bdsContents string, changeEnumFile string, testSuffix string) *tscInput {
+ return &tscInput{
+ subScenario: "const enums" + testSuffix,
+ files: FileMap{
+ "/home/src/workspaces/project/a.ts": stringtestutil.Dedent(`
+ import {A} from "./c"
+ let a = A.ONE
+ `),
+ "/home/src/workspaces/project/b.d.ts": stringtestutil.Dedent(bdsContents),
+ "/home/src/workspaces/project/c.ts": stringtestutil.Dedent(`
+ import {A} from "./b"
+ let b = A.ONE
+ export {A}
+ `),
+ "/home/src/workspaces/project/worker.d.ts": stringtestutil.Dedent(`
+ export const enum AWorker {
+ ONE = 1
+ }
+ `),
+ },
+ commandLineArgs: []string{"-i", `a.ts`, "--tsbuildinfofile", "a.tsbuildinfo"},
+ edits: []*tscEdit{
+ {
+ caption: "change enum value",
+ edit: func(sys *testSys) {
+ sys.replaceFileText(changeEnumFile, "1", "2")
+ },
+ },
+ {
+ caption: "change enum value again",
+ edit: func(sys *testSys) {
+ sys.replaceFileText(changeEnumFile, "2", "3")
+ },
+ },
+ {
+ caption: "something else changes in b.d.ts",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/project/b.d.ts", "export const randomThing = 10;")
+ },
+ },
+ {
+ caption: "something else changes in b.d.ts again",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/project/b.d.ts", "export const randomThing2 = 10;")
+ },
+ },
+ },
+ }
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "serializing error chain",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "strict": true,
+ "jsx": "react",
+ "module": "esnext",
+ },
+ }`),
+ "/home/src/workspaces/project/index.tsx": stringtestutil.Dedent(`
+ declare namespace JSX {
+ interface ElementChildrenAttribute { children: {}; }
+ interface IntrinsicElements { div: {} }
+ }
+
+ declare var React: any;
+
+ declare function Component(props: never): any;
+ declare function Component(props: { children?: number }): any;
+ (
+
+
+ )`),
+ },
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "serializing composite project",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "strict": true,
+ "module": "esnext",
+ },
+ }`),
+ "/home/src/workspaces/project/index.tsx": `export const a = 1;`,
+ "/home/src/workspaces/project/other.ts": `export const b = 2;`,
+ },
+ },
+ {
+ subScenario: "change to modifier of class expression field with declaration emit enabled",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "esnext",
+ "declaration": true
+ }
+ }`),
+ "/home/src/workspaces/project/main.ts": stringtestutil.Dedent(`
+ import MessageablePerson from './MessageablePerson.js';
+ function logMessage( person: MessageablePerson ) {
+ console.log( person.message );
+ }`),
+ "/home/src/workspaces/project/MessageablePerson.ts": stringtestutil.Dedent(`
+ const Messageable = () => {
+ return class MessageableClass {
+ public message = 'hello';
+ }
+ };
+ const wrapper = () => Messageable();
+ type MessageablePerson = InstanceType>;
+ export default MessageablePerson;`),
+ tscLibPath + "/lib.d.ts": tscDefaultLibContent + "\n" + stringtestutil.Dedent(`
+ type ReturnType any> = T extends (...args: any) => infer R ? R : any;
+ type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;`),
+ },
+ commandLineArgs: []string{"--incremental"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "modify public to protected",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "public", "protected")
+ },
+ },
+ noChange,
+ {
+ caption: "modify protected to public",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "protected", "public")
+ },
+ },
+ noChange,
+ },
+ },
+ {
+ subScenario: "change to modifier of class expression field",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "esnext"
+ }
+ }`),
+ "/home/src/workspaces/project/main.ts": stringtestutil.Dedent(`
+ import MessageablePerson from './MessageablePerson.js';
+ function logMessage( person: MessageablePerson ) {
+ console.log( person.message );
+ }`),
+ "/home/src/workspaces/project/MessageablePerson.ts": stringtestutil.Dedent(`
+ const Messageable = () => {
+ return class MessageableClass {
+ public message = 'hello';
+ }
+ };
+ const wrapper = () => Messageable();
+ type MessageablePerson = InstanceType>;
+ export default MessageablePerson;`),
+ tscLibPath + "/lib.d.ts": tscDefaultLibContent + "\n" + stringtestutil.Dedent(`
+ type ReturnType any> = T extends (...args: any) => infer R ? R : any;
+ type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;`),
+ },
+ commandLineArgs: []string{"--incremental"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "modify public to protected",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "public", "protected")
+ },
+ },
+ noChange,
+ {
+ caption: "modify protected to public",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "protected", "public")
+ },
+ },
+ noChange,
+ },
+ },
+ {
+ subScenario: "when passing filename for buildinfo on commandline",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs"
+ },
+ "include": [
+ "src/**/*.ts"
+ ],
+ }`),
+ },
+ commandLineArgs: []string{"--incremental", "--tsBuildInfoFile", ".tsbuildinfo", "--explainFiles"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "when passing rootDir from commandline",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "outDir": "dist"
+ }
+ }`),
+ },
+ commandLineArgs: []string{"--rootDir", "src"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "with only dts files",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.d.ts": "export const x = 10;",
+ "/home/src/workspaces/project/src/another.d.ts": "export const y = 10;",
+ "/home/src/workspaces/project/tsconfig.json": "{}",
+ },
+ commandLineArgs: []string{"--incremental"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "modify d.ts file",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/project/src/main.d.ts", "export const xy = 100;")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when passing rootDir is in the tsconfig",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "outDir": "dist",
+ "rootDir": "./"
+ }
+ }`),
+ },
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "tsbuildinfo has error",
+ files: FileMap{
+ "/home/src/workspaces/project/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": "{}",
+ "/home/src/workspaces/project/tsconfig.tsbuildinfo": "Some random string",
+ },
+ commandLineArgs: []string{"-i"},
+ edits: []*tscEdit{
+ {
+ caption: "tsbuildinfo written has error",
+ edit: func(sys *testSys) {
+ sys.prependFile("/home/src/workspaces/project/tsconfig.tsbuildinfo", "Some random string")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when global file is added, the signatures are updated",
+ files: FileMap{
+ "/home/src/workspaces/project/src/main.ts": stringtestutil.Dedent(`
+ ///
+ ///
+ function main() { }
+ `),
+ "/home/src/workspaces/project/src/anotherFileWithSameReferenes.ts": stringtestutil.Dedent(`
+ ///
+ ///
+ function anotherFileWithSameReferenes() { }
+ `),
+ "/home/src/workspaces/project/src/filePresent.ts": `function something() { return 10; }`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "include": ["src/**/*.ts"],
+ }`),
+ },
+ commandLineArgs: []string{},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "Modify main file",
+ edit: func(sys *testSys) {
+ sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`)
+ },
+ },
+ {
+ caption: "Modify main file again",
+ edit: func(sys *testSys) {
+ sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`)
+ },
+ },
+ {
+ caption: "Add new file and update main file",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError(`/home/src/workspaces/project/src/newFile.ts`, "function foo() { return 20; }", false)
+ sys.prependFile(
+ `/home/src/workspaces/project/src/main.ts`,
+ `///
+`,
+ )
+ sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `foo();`)
+ },
+ },
+ {
+ caption: "Write file that could not be resolved",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError(`/home/src/workspaces/project/src/fileNotFound.ts`, "function something2() { return 20; }", false)
+ },
+ },
+ {
+ caption: "Modify main file",
+ edit: func(sys *testSys) {
+ sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "react-jsx-emit-mode with no backing types found doesnt crash",
+ files: FileMap{
+ "/home/src/workspaces/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
+ "/home/src/workspaces/project/node_modules/@types/react/index.d.ts": stringtestutil.Dedent(`
+ export {};
+ declare global {
+ namespace JSX {
+ interface Element {}
+ interface IntrinsicElements {
+ div: {
+ propA?: boolean;
+ };
+ }
+ }
+ }`), // doesn't contain a jsx-runtime definition
+ "/home/src/workspaces/project/src/index.tsx": `export const App = () => ;`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "commonjs",
+ "jsx": "react-jsx",
+ "incremental": true,
+ "jsxImportSource": "react"
+ }
+ }`),
+ },
+ },
+ {
+ subScenario: "react-jsx-emit-mode with no backing types found doesnt crash under --strict",
+ files: FileMap{
+ "/home/src/workspaces/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
+ "/home/src/workspaces/project/node_modules/@types/react/index.d.ts": stringtestutil.Dedent(`
+ export {};
+ declare global {
+ namespace JSX {
+ interface Element {}
+ interface IntrinsicElements {
+ div: {
+ propA?: boolean;
+ };
+ }
+ }
+ }`), // doesn't contain a jsx-runtime definition
+ "/home/src/workspaces/project/src/index.tsx": `export const App = () => ;`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "commonjs",
+ "jsx": "react-jsx",
+ "incremental": true,
+ "jsxImportSource": "react"
+ }
+ }`),
+ },
+ commandLineArgs: []string{"--strict"},
+ },
+ {
+ subScenario: "change to type that gets used as global through export in another file",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true
+ }
+ }`),
+ "/home/src/workspaces/project/class1.ts": stringtestutil.Dedent(`
+ const a: MagicNumber = 1;
+ console.log(a);`),
+ "/home/src/workspaces/project/constants.ts": "export default 1;",
+ "/home/src/workspaces/project/types.d.ts": `type MagicNumber = typeof import('./constants').default`,
+ },
+ edits: []*tscEdit{
+ {
+ caption: "Modify imports used in global file",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/workspaces/project/constants.ts", "export default 2;", false)
+ },
+ expectedDiff: "Currently there is issue with d.ts emit for export default = 1 to widen in dts which is why we are not re-computing errors and results in incorrect error reporting",
+ },
+ },
+ },
+ {
+ subScenario: "change to type that gets used as global through export in another file through indirect import",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true
+ }
+ }`),
+ "/home/src/workspaces/project/class1.ts": stringtestutil.Dedent(`
+ const a: MagicNumber = 1;
+ console.log(a);`),
+ "/home/src/workspaces/project/constants.ts": "export default 1;",
+ "/home/src/workspaces/project/reexport.ts": `export { default as ConstantNumber } from "./constants"`,
+ "/home/src/workspaces/project/types.d.ts": `type MagicNumber = typeof import('./reexport').ConstantNumber`,
+ },
+ edits: []*tscEdit{
+ {
+ caption: "Modify imports used in global file",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/workspaces/project/constants.ts", "export default 2;", false)
+ },
+ expectedDiff: "Currently there is issue with d.ts emit for export default = 1 to widen in dts which is why we are not re-computing errors and results in incorrect error reporting",
+ },
+ },
+ },
+ {
+ subScenario: "when file is deleted",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "outDir"
+ }
+ }`),
+ "/home/src/workspaces/project/file1.ts": `export class C { }`,
+ "/home/src/workspaces/project/file2.ts": `export class D { }`,
+ },
+ edits: []*tscEdit{
+ {
+ caption: "delete file with imports",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/project/file2.ts")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "generates typerefs correctly",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "outDir",
+ "checkJs": true
+ },
+ "include": ["src"],
+ }`),
+ "/home/src/workspaces/project/src/box.ts": stringtestutil.Dedent(`
+ export interface Box {
+ unbox(): T
+ }
+ `),
+ "/home/src/workspaces/project/src/bug.js": stringtestutil.Dedent(`
+ import * as B from "./box.js"
+ import * as W from "./wrap.js"
+
+ /**
+ * @template {object} C
+ * @param {C} source
+ * @returns {W.Wrap}
+ */
+ const wrap = source => {
+ throw source
+ }
+
+ /**
+ * @returns {B.Box}
+ */
+ const box = (n = 0) => ({ unbox: () => n })
+
+ export const bug = wrap({ n: box(1) });
+ `),
+ "/home/src/workspaces/project/src/wrap.ts": stringtestutil.Dedent(`
+ export type Wrap = {
+ [K in keyof C]: { wrapped: C[K] }
+ }
+ `),
+ },
+ edits: []*tscEdit{
+ {
+ caption: "modify js file",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/project/src/bug.js", `export const something = 1;`)
+ },
+ },
+ },
+ },
+ getConstEnumTest(`
+ export const enum A {
+ ONE = 1
+ }
+ `, "/home/src/workspaces/project/b.d.ts", ""),
+ getConstEnumTest(`
+ export const enum AWorker {
+ ONE = 1
+ }
+ export { AWorker as A };
+ `, "/home/src/workspaces/project/b.d.ts", " aliased"),
+ getConstEnumTest(`export { AWorker as A } from "./worker";`, "/home/src/workspaces/project/worker.d.ts", " aliased in different file"),
+ {
+ subScenario: "option changes with composite",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ }
+ }`),
+ "/home/src/workspaces/project/a.ts": `export const a = 10;const aLocal = 10;`,
+ "/home/src/workspaces/project/b.ts": `export const b = 10;const bLocal = 10;`,
+ "/home/src/workspaces/project/c.ts": `import { a } from "./a";export const c = a;`,
+ "/home/src/workspaces/project/d.ts": `import { b } from "./b";export const d = b;`,
+ },
+ edits: []*tscEdit{
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--sourceMap"},
+ },
+ {
+ caption: "should re-emit only js so they dont contain sourcemap",
+ },
+ {
+ caption: "with declaration should not emit anything",
+ commandLineArgs: []string{"--declaration"},
+ // discrepancyExplanation: () => [
+ // `Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/-/g, "")}`,
+ // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
+ // ],
+ },
+ noChange,
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--declaration", "--declarationMap"},
+ },
+ {
+ caption: "should re-emit only dts so they dont contain sourcemap",
+ },
+ {
+ caption: "with emitDeclarationOnly should not emit anything",
+ commandLineArgs: []string{"--emitDeclarationOnly"},
+ // discrepancyExplanation: () => [
+ // `Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/-/g, "")}`,
+ // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
+ // ],
+ },
+ noChange,
+ {
+ caption: "local change",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10")
+ },
+ },
+ {
+ caption: "with declaration should not emit anything",
+ commandLineArgs: []string{"--declaration"},
+ // discrepancyExplanation: () => [
+ // `Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/-/g, "")}`,
+ // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
+ // ],
+ },
+ {
+ caption: "with inlineSourceMap",
+ commandLineArgs: []string{"--inlineSourceMap"},
+ },
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--sourceMap"},
+ },
+ {
+ caption: "declarationMap enabling",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", `"composite": true,`, `"composite": true, "declarationMap": true`)
+ },
+ },
+ {
+ caption: "with sourceMap should not emit d.ts",
+ commandLineArgs: []string{"--sourceMap"},
+ },
+ },
+ },
+ {
+ subScenario: "option changes with incremental",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ }
+ }`),
+ "/home/src/workspaces/project/a.ts": `export const a = 10;const aLocal = 10;`,
+ "/home/src/workspaces/project/b.ts": `export const b = 10;const bLocal = 10;`,
+ "/home/src/workspaces/project/c.ts": `import { a } from "./a";export const c = a;`,
+ "/home/src/workspaces/project/d.ts": `import { b } from "./b";export const d = b;`,
+ },
+ edits: []*tscEdit{
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--sourceMap"},
+ },
+ {
+ caption: "should re-emit only js so they dont contain sourcemap",
+ },
+ {
+ caption: "with declaration, emit Dts and should not emit js",
+ commandLineArgs: []string{"--declaration"},
+ },
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--declaration", "--declarationMap"},
+ },
+ {
+ caption: "no change",
+ // discrepancyExplanation: () => [
+ // `Clean build tsbuildinfo will have compilerOptions {}`,
+ // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option declaration and declarationMap`,
+ // ],
+ },
+ {
+ caption: "local change",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10")
+ },
+ },
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--declaration", "--declarationMap"},
+ },
+ {
+ caption: "no change",
+ // discrepancyExplanation: () => [
+ // `Clean build tsbuildinfo will have compilerOptions {}`,
+ // `Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option declaration and declarationMap`,
+ // ],
+ },
+ {
+ caption: "with inlineSourceMap",
+ commandLineArgs: []string{"--inlineSourceMap"},
+ },
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--sourceMap"},
+ },
+ {
+ caption: "emit js files",
+ },
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--declaration", "--declarationMap"},
+ },
+ {
+ caption: "with declaration and declarationMap, should not re-emit",
+ commandLineArgs: []string{"--declaration", "--declarationMap"},
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "incremental")
+ }
+}
+
+func TestTscLibraryResolution(t *testing.T) {
+ t.Parallel()
+ getTscLibraryResolutionFileMap := func(libReplacement bool) FileMap {
+ files := FileMap{
+ "/home/src/workspace/projects/project1/utils.d.ts": `export const y = 10;`,
+ "/home/src/workspace/projects/project1/file.ts": `export const file = 10;`,
+ "/home/src/workspace/projects/project1/core.d.ts": `export const core = 10;`,
+ "/home/src/workspace/projects/project1/index.ts": `export const x = "type1";`,
+ "/home/src/workspace/projects/project1/file2.ts": stringtestutil.Dedent(`
+ ///
+ ///
+ ///
+ `),
+ "/home/src/workspace/projects/project1/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "typeRoots": ["./typeroot1"],
+ "lib": ["es5", "dom"],
+ "traceResolution": true,
+ "libReplacement": %t
+ }
+ }
+ `, libReplacement)),
+ "/home/src/workspace/projects/project1/typeroot1/sometype/index.d.ts": `export type TheNum = "type1";`,
+ "/home/src/workspace/projects/project2/utils.d.ts": `export const y = 10;`,
+ "/home/src/workspace/projects/project2/index.ts": `export const y = 10`,
+ "/home/src/workspace/projects/project2/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "lib": ["es5", "dom"],
+ "traceResolution": true,
+ "libReplacement": %t
+ }
+ }
+ `, libReplacement)),
+ "/home/src/workspace/projects/project3/utils.d.ts": `export const y = 10;`,
+ "/home/src/workspace/projects/project3/index.ts": `export const z = 10`,
+ "/home/src/workspace/projects/project3/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "lib": ["es5", "dom"],
+ "traceResolution": true,
+ "libReplacement": %t
+ }
+ }
+ `, libReplacement)),
+ "/home/src/workspace/projects/project4/utils.d.ts": `export const y = 10;`,
+ "/home/src/workspace/projects/project4/index.ts": `export const z = 10`,
+ "/home/src/workspace/projects/project4/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "lib": ["esnext", "dom", "webworker"],
+ "traceResolution": true,
+ "libReplacement": %t
+ }
+ }
+ `, libReplacement)),
+ getTestLibPathFor("dom"): "interface DOMInterface { }",
+ getTestLibPathFor("webworker"): "interface WebWorkerInterface { }",
+ getTestLibPathFor("scripthost"): "interface ScriptHostInterface { }",
+ "/home/src/workspace/projects/node_modules/@typescript/unlreated/index.d.ts": "export const unrelated = 10;",
+ }
+ if libReplacement {
+ files["/home/src/workspace/projects/node_modules/@typescript/lib-es5/index.d.ts"] = tscDefaultLibContent
+ files["/home/src/workspace/projects/node_modules/@typescript/lib-esnext/index.d.ts"] = tscDefaultLibContent
+ files["/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts"] = "interface DOMInterface { }"
+ files["/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts"] = "interface WebWorkerInterface { }"
+ files["/home/src/workspace/projects/node_modules/@typescript/lib-scripthost/index.d.ts"] = "interface ScriptHostInterface { }"
+ }
+ return files
+ }
+ getTscLibResolutionTestCases := func(commandLineArgs []string) []*tscInput {
+ return []*tscInput{
+ {
+ subScenario: "with config",
+ files: getTscLibraryResolutionFileMap(false),
+ cwd: "/home/src/workspace/projects",
+ commandLineArgs: commandLineArgs,
+ },
+ {
+ subScenario: "with config with libReplacement",
+ files: getTscLibraryResolutionFileMap(true),
+ cwd: "/home/src/workspace/projects",
+ commandLineArgs: commandLineArgs,
+ },
+ }
+ }
+ getTscLibraryResolutionUnknown := func() FileMap {
+ return FileMap{
+ "/home/src/workspace/projects/project1/utils.d.ts": `export const y = 10;`,
+ "/home/src/workspace/projects/project1/file.ts": `export const file = 10;`,
+ "/home/src/workspace/projects/project1/core.d.ts": `export const core = 10;`,
+ "/home/src/workspace/projects/project1/index.ts": `export const x = "type1";`,
+ "/home/src/workspace/projects/project1/file2.ts": stringtestutil.Dedent(`
+ ///
+ ///
+ ///
+ `),
+ "/home/src/workspace/projects/project1/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "traceResolution": true,
+ "libReplacement": true
+ }
+ }`),
+ getTestLibPathFor("webworker"): "interface WebWorkerInterface { }",
+ getTestLibPathFor("scripthost"): "interface ScriptHostInterface { }",
+ }
+ }
+ testCases := slices.Concat(
+ getTscLibResolutionTestCases([]string{"-b", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles"}),
+ getTscLibResolutionTestCases([]string{"-p", "project1", "--explainFiles"}),
+ []*tscInput{
+ {
+ subScenario: "unknown lib",
+ files: getTscLibraryResolutionUnknown(),
+ cwd: "/home/src/workspace/projects",
+ commandLineArgs: []string{"-p", "project1", "--explainFiles"},
+ },
+ {
+ subScenario: "when noLib toggles",
+ files: FileMap{
+ "/home/src/workspaces/project/a.d.ts": `declare const a = "hello";`,
+ "/home/src/workspaces/project/b.ts": `const b = 10;`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "declaration": true,
+ "incremental": true,
+ "lib": ["es6"],
+ },
+ }
+ `),
+ },
+ edits: []*tscEdit{
+ {
+ caption: "with --noLib",
+ commandLineArgs: []string{"--noLib"},
+ },
+ },
+ },
+ },
+ )
+
+ for _, test := range testCases {
+ test.run(t, "libraryResolution")
+ }
+}
+
+func TestTscListFilesOnly(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "loose file",
+ files: FileMap{
+ "/home/src/workspaces/project/test.ts": "export const x = 1;",
+ },
+ commandLineArgs: []string{"test.ts", "--listFilesOnly"},
+ },
+ {
+ subScenario: "combined with incremental",
+ files: FileMap{
+ "/home/src/workspaces/project/test.ts": "export const x = 1;",
+ "/home/src/workspaces/project/tsconfig.json": "{}",
+ },
+ commandLineArgs: []string{"--incremental", "--listFilesOnly"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental actual build",
+ commandLineArgs: []string{"--incremental"},
+ },
+ noChange,
+ {
+ caption: "incremental should not build",
+ commandLineArgs: []string{"--incremental"},
+ },
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ testCase.run(t, "listFilesOnly")
+ }
+}
+
+func TestTscModuleResolution(t *testing.T) {
+ t.Parallel()
+ getBuildModuleResolutionInProjectRefTestCase := func(preserveSymlinks bool) *tscInput {
+ return &tscInput{
+ subScenario: `resolves specifier in output declaration file from referenced project correctly` + core.IfElse(preserveSymlinks, " with preserveSymlinks", ""),
+ files: FileMap{
+ `/user/username/projects/myproject/packages/pkg1/index.ts`: stringtestutil.Dedent(`
+ import type { TheNum } from 'pkg2'
+ export const theNum: TheNum = 42;`),
+ `/user/username/projects/myproject/packages/pkg1/tsconfig.json`: stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "outDir": "build",
+ "preserveSymlinks": %t
+ },
+ "references": [{ "path": "../pkg2" }]
+ }
+ `, preserveSymlinks)),
+ `/user/username/projects/myproject/packages/pkg2/const.ts`: stringtestutil.Dedent(`
+ export type TheNum = 42;
+ `),
+ `/user/username/projects/myproject/packages/pkg2/index.ts`: stringtestutil.Dedent(`
+ export type { TheNum } from 'const';
+ `),
+ `/user/username/projects/myproject/packages/pkg2/tsconfig.json`: stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "build",
+ "paths": {
+ "const": ["./const"]
+ },
+ "preserveSymlinks": %t,
+ },
+ }
+ `, preserveSymlinks)),
+ `/user/username/projects/myproject/packages/pkg2/package.json`: stringtestutil.Dedent(`
+ {
+ "name": "pkg2",
+ "version": "1.0.0",
+ "main": "build/index.js"
+ }
+ `),
+ `/user/username/projects/myproject/node_modules/pkg2`: vfstest.Symlink(`/user/username/projects/myproject/packages/pkg2`),
+ },
+ cwd: "/user/username/projects/myproject",
+ commandLineArgs: []string{"-b", "packages/pkg1", "--verbose", "--traceResolution"},
+ }
+ }
+ getTscModuleResolutionSharingFileMap := func() FileMap {
+ return FileMap{
+ "/home/src/workspaces/project/packages/a/index.js": `export const a = 'a';`,
+ "/home/src/workspaces/project/packages/a/test/index.js": `import 'a';`,
+ "/home/src/workspaces/project/packages/a/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "checkJs": true,
+ "composite": true,
+ "declaration": true,
+ "emitDeclarationOnly": true,
+ "module": "nodenext",
+ "outDir": "types",
+ },
+ }`),
+ "/home/src/workspaces/project/packages/a/package.json": stringtestutil.Dedent(`
+ {
+ "name": "a",
+ "version": "0.0.0",
+ "type": "module",
+ "exports": {
+ ".": {
+ "types": "./types/index.d.ts",
+ "default": "./index.js"
+ }
+ }
+ }`),
+ "/home/src/workspaces/project/packages/b/index.js": `export { a } from 'a';`,
+ "/home/src/workspaces/project/packages/b/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [{ "path": "../a" }],
+ "compilerOptions": {
+ "checkJs": true,
+ "module": "nodenext",
+ "noEmit": true,
+ "noImplicitAny": true,
+ },
+ }`),
+ "/home/src/workspaces/project/packages/b/package.json": stringtestutil.Dedent(`
+ {
+ "name": "b",
+ "version": "0.0.0",
+ "type": "module"
+ }`),
+ "/home/src/workspaces/project/node_modules/a": vfstest.Symlink("/home/src/workspaces/project/packages/a"),
+ }
+ }
+ getTscModuleResolutionAlternateResultAtTypesPackageJson := func(packageName string, addTypesCondition bool) string {
+ var typesString string
+ if addTypesCondition {
+ typesString = `"types": "./index.d.ts",`
+ }
+ return stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "name": "@types/%s",
+ "version": "1.0.0",
+ "types": "index.d.ts",
+ "exports": {
+ ".": {
+ %s
+ "require": "./index.d.ts"
+ }
+ }
+ }`, packageName, typesString))
+ }
+ getTscModuleResolutionAlternateResultPackageJson := func(packageName string, addTypes bool, addTypesCondition bool) string {
+ var types string
+ if addTypes {
+ types = `"types": "index.d.ts",`
+ }
+ var typesString string
+ if addTypesCondition {
+ typesString = `"types": "./index.d.ts",`
+ }
+ return stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "name": "%s",
+ "version": "1.0.0",
+ "main": "index.js",
+ %s
+ "exports": {
+ ".": {
+ %s
+ "import": "./index.mjs",
+ "require": "./index.js"
+ }
+ }
+ }`, packageName, types, typesString))
+ }
+ getTscModuleResolutionAlternateResultDts := func(packageName string) string {
+ return fmt.Sprintf(`export declare const %s: number;`, packageName)
+ }
+ getTscModuleResolutionAlternateResultJs := func(packageName string) string {
+ return fmt.Sprintf(`module.exports = { %s: 1 };`, packageName)
+ }
+ getTscModuleResolutionAlternateResultMjs := func(packageName string) string {
+ return fmt.Sprintf(`export const %s = 1;`, packageName)
+ }
+ testCases := []*tscInput{
+ getBuildModuleResolutionInProjectRefTestCase(false),
+ getBuildModuleResolutionInProjectRefTestCase(true),
+ {
+ subScenario: `type reference resolution uses correct options for different resolution options referenced project`,
+ files: FileMap{
+ "/home/src/workspaces/project/packages/pkg1_index.ts": `export const theNum: TheNum = "type1";`,
+ "/home/src/workspaces/project/packages/pkg1.tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "typeRoots": ["./typeroot1"]
+ },
+ "files": ["./pkg1_index.ts"],
+ }
+ `),
+ "/home/src/workspaces/project/packages/typeroot1/sometype/index.d.ts": `declare type TheNum = "type1";`,
+ "/home/src/workspaces/project/packages/pkg2_index.ts": `export const theNum: TheNum2 = "type2";`,
+ "/home/src/workspaces/project/packages/pkg2.tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "typeRoots": ["./typeroot2"]
+ },
+ "files": ["./pkg2_index.ts"],
+ }
+ `),
+ "/home/src/workspaces/project/packages/typeroot2/sometype/index.d.ts": `declare type TheNum2 = "type2";`,
+ },
+ commandLineArgs: []string{"-b", "packages/pkg1.tsconfig.json", "packages/pkg2.tsconfig.json", "--verbose", "--traceResolution"},
+ },
+ {
+ subScenario: "impliedNodeFormat differs between projects for shared file",
+ files: FileMap{
+ "/home/src/workspaces/project/a/src/index.ts": "",
+ "/home/src/workspaces/project/a/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "strict": true
+ }
+ }
+ `),
+ "/home/src/workspaces/project/b/src/index.ts": stringtestutil.Dedent(`
+ import pg from "pg";
+ pg.foo();
+ `),
+ "/home/src/workspaces/project/b/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "strict": true,
+ "module": "node16"
+ },
+ }`),
+ "/home/src/workspaces/project/b/package.json": stringtestutil.Dedent(`
+ {
+ "name": "b",
+ "type": "module"
+ }`),
+ "/home/src/workspaces/project/node_modules/@types/pg/index.d.ts": "export function foo(): void;",
+ "/home/src/workspaces/project/node_modules/@types/pg/package.json": stringtestutil.Dedent(`
+ {
+ "name": "@types/pg",
+ "types": "index.d.ts"
+ }`),
+ },
+ commandLineArgs: []string{"-b", "a", "b", "--verbose", "--traceResolution", "--explainFiles"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "shared resolution should not report error",
+ files: getTscModuleResolutionSharingFileMap(),
+ commandLineArgs: []string{"-b", "packages/b", "--verbose", "--traceResolution", "--explainFiles"},
+ },
+ {
+ subScenario: "when resolution is not shared",
+ files: getTscModuleResolutionSharingFileMap(),
+ commandLineArgs: []string{"-b", "packages/a", "--verbose", "--traceResolution", "--explainFiles"},
+ edits: []*tscEdit{
+ {
+ caption: "build b",
+ commandLineArgs: []string{"-b", "packages/b", "--verbose", "--traceResolution", "--explainFiles"},
+ },
+ },
+ },
+ {
+ subScenario: "pnpm style layout",
+ files: FileMap{
+ // button@0.0.1
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.1/node_modules/@component-type-checker/button/src/index.ts": stringtestutil.Dedent(`
+ export interface Button {
+ a: number;
+ b: number;
+ }
+ export function createButton(): Button {
+ return {
+ a: 0,
+ b: 1,
+ };
+ }
+ `),
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.1/node_modules/@component-type-checker/button/package.json": stringtestutil.Dedent(`
+ {
+ "name": "@component-type-checker/button",
+ "version": "0.0.1",
+ "main": "./src/index.ts"
+ }`),
+
+ // button@0.0.2
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.2/node_modules/@component-type-checker/button/src/index.ts": stringtestutil.Dedent(`
+ export interface Button {
+ a: number;
+ c: number;
+ }
+ export function createButton(): Button {
+ return {
+ a: 0,
+ c: 2,
+ };
+ }
+ `),
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.2/node_modules/@component-type-checker/button/package.json": stringtestutil.Dedent(`
+ {
+ "name": "@component-type-checker/button",
+ "version": "0.0.2",
+ "main": "./src/index.ts"
+ }`),
+
+ // @component-type-checker+components@0.0.1_@component-type-checker+button@0.0.1
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.1/node_modules/@component-type-checker/button": vfstest.Symlink(
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.1/node_modules/@component-type-checker/button",
+ ),
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.1/node_modules/@component-type-checker/components/src/index.ts": stringtestutil.Dedent(`
+ export { createButton, Button } from "@component-type-checker/button";
+ `),
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.1/node_modules/@component-type-checker/components/package.json": stringtestutil.Dedent(`
+ {
+ "name": "@component-type-checker/components",
+ "version": "0.0.1",
+ "main": "./src/index.ts",
+ "peerDependencies": {
+ "@component-type-checker/button": "*"
+ },
+ "devDependencies": {
+ "@component-type-checker/button": "0.0.2"
+ }
+ }`),
+
+ // @component-type-checker+components@0.0.1_@component-type-checker+button@0.0.2
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.2/node_modules/@component-type-checker/button": vfstest.Symlink(
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.2/node_modules/@component-type-checker/button",
+ ),
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.2/node_modules/@component-type-checker/components/src/index.ts": stringtestutil.Dedent(`
+ export { createButton, Button } from "@component-type-checker/button";
+ `),
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.2/node_modules/@component-type-checker/components/package.json": stringtestutil.Dedent(`
+ {
+ "name": "@component-type-checker/components",
+ "version": "0.0.1",
+ "main": "./src/index.ts",
+ "peerDependencies": {
+ "@component-type-checker/button": "*"
+ },
+ "devDependencies": {
+ "@component-type-checker/button": "0.0.2"
+ }
+ }`),
+
+ // sdk => @component-type-checker+components@0.0.1_@component-type-checker+button@0.0.1
+ "/home/src/projects/component-type-checker/packages/sdk/src/index.ts": stringtestutil.Dedent(`
+ export { Button, createButton } from "@component-type-checker/components";
+ export const VERSION = "0.0.2";
+ `),
+ "/home/src/projects/component-type-checker/packages/sdk/package.json": stringtestutil.Dedent(`
+ {
+ "name": "@component-type-checker/sdk1",
+ "version": "0.0.2",
+ "main": "./src/index.ts",
+ "dependencies": {
+ "@component-type-checker/components": "0.0.1",
+ "@component-type-checker/button": "0.0.1"
+ }
+ }`),
+ "/home/src/projects/component-type-checker/packages/sdk/node_modules/@component-type-checker/button": vfstest.Symlink(
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.1/node_modules/@component-type-checker/button",
+ ),
+ "/home/src/projects/component-type-checker/packages/sdk/node_modules/@component-type-checker/components": vfstest.Symlink(
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.1/node_modules/@component-type-checker/components",
+ ),
+
+ // app => @component-type-checker+components@0.0.1_@component-type-checker+button@0.0.2
+ "/home/src/projects/component-type-checker/packages/app/src/app.tsx": stringtestutil.Dedent(`
+ import { VERSION } from "@component-type-checker/sdk";
+ import { Button } from "@component-type-checker/components";
+ import { createButton } from "@component-type-checker/button";
+ const button: Button = createButton();
+ `),
+ "/home/src/projects/component-type-checker/packages/app/package.json": stringtestutil.Dedent(`
+ {
+ "name": "app",
+ "version": "1.0.0",
+ "dependencies": {
+ "@component-type-checker/button": "0.0.2",
+ "@component-type-checker/components": "0.0.1",
+ "@component-type-checker/sdk": "0.0.2"
+ }
+ }`),
+ "/home/src/projects/component-type-checker/packages/app/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "module": "esnext",
+ "lib": ["ES5"],
+ "moduleResolution": "node",
+ "outDir": "dist",
+ },
+ "include": ["src"],
+ }`),
+ "/home/src/projects/component-type-checker/packages/app/node_modules/@component-type-checker/button": vfstest.Symlink(
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.2/node_modules/@component-type-checker/button",
+ ),
+ "/home/src/projects/component-type-checker/packages/app/node_modules/@component-type-checker/components": vfstest.Symlink(
+ "/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+components@0.0.1_@component-type-checker+button@0.0.2/node_modules/@component-type-checker/components",
+ ),
+ "/home/src/projects/component-type-checker/packages/app/node_modules/@component-type-checker/sdk": vfstest.Symlink(
+ "/home/src/projects/component-type-checker/packages/sdk",
+ ),
+ },
+ cwd: "/home/src/projects/component-type-checker/packages/app",
+ commandLineArgs: []string{"--traceResolution", "--explainFiles"},
+ },
+ {
+ subScenario: "package json scope",
+ files: FileMap{
+ "/home/src/workspaces/project/src/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "ES2016",
+ "composite": true,
+ "module": "Node16",
+ "traceResolution": true,
+ },
+ "files": [
+ "main.ts",
+ "fileA.ts",
+ "fileB.mts",
+ ],
+ }`),
+ "/home/src/workspaces/project/src/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/src/fileA.ts": stringtestutil.Dedent(`
+ import { foo } from "./fileB.mjs";
+ foo();
+ `),
+ "/home/src/workspaces/project/src/fileB.mts": "export function foo() {}",
+ "/home/src/workspaces/project/package.json": stringtestutil.Dedent(`
+ {
+ "name": "app",
+ "version": "1.0.0"
+ }
+ `),
+ },
+ commandLineArgs: []string{"-p", "src", "--explainFiles", "--extendedDiagnostics"},
+ edits: []*tscEdit{
+ {
+ caption: "Delete package.json",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/project/package.json")
+ },
+ // !!! repopulateInfo on diagnostics not yet implemented
+ expectedDiff: "Currently we arent repopulating error chain so errors will be different",
+ },
+ },
+ },
+ {
+ subScenario: "alternateResult",
+ files: FileMap{
+ "/home/src/projects/project/node_modules/@types/bar/package.json": getTscModuleResolutionAlternateResultAtTypesPackageJson("bar" /*addTypesCondition*/, false),
+ "/home/src/projects/project/node_modules/@types/bar/index.d.ts": getTscModuleResolutionAlternateResultDts("bar"),
+ "/home/src/projects/project/node_modules/bar/package.json": getTscModuleResolutionAlternateResultPackageJson("bar" /*addTypes*/, false /*addTypesCondition*/, false),
+ "/home/src/projects/project/node_modules/bar/index.js": getTscModuleResolutionAlternateResultJs("bar"),
+ "/home/src/projects/project/node_modules/bar/index.mjs": getTscModuleResolutionAlternateResultMjs("bar"),
+ "/home/src/projects/project/node_modules/foo/package.json": getTscModuleResolutionAlternateResultPackageJson("foo" /*addTypes*/, true /*addTypesCondition*/, false),
+ "/home/src/projects/project/node_modules/foo/index.js": getTscModuleResolutionAlternateResultJs("foo"),
+ "/home/src/projects/project/node_modules/foo/index.mjs": getTscModuleResolutionAlternateResultMjs("foo"),
+ "/home/src/projects/project/node_modules/foo/index.d.ts": getTscModuleResolutionAlternateResultDts("foo"),
+ "/home/src/projects/project/node_modules/@types/bar2/package.json": getTscModuleResolutionAlternateResultAtTypesPackageJson("bar2" /*addTypesCondition*/, true),
+ "/home/src/projects/project/node_modules/@types/bar2/index.d.ts": getTscModuleResolutionAlternateResultDts("bar2"),
+ "/home/src/projects/project/node_modules/bar2/package.json": getTscModuleResolutionAlternateResultPackageJson("bar2" /*addTypes*/, false /*addTypesCondition*/, false),
+ "/home/src/projects/project/node_modules/bar2/index.js": getTscModuleResolutionAlternateResultJs("bar2"),
+ "/home/src/projects/project/node_modules/bar2/index.mjs": getTscModuleResolutionAlternateResultMjs("bar2"),
+ "/home/src/projects/project/node_modules/foo2/package.json": getTscModuleResolutionAlternateResultPackageJson("foo2" /*addTypes*/, true /*addTypesCondition*/, true),
+ "/home/src/projects/project/node_modules/foo2/index.js": getTscModuleResolutionAlternateResultJs("foo2"),
+ "/home/src/projects/project/node_modules/foo2/index.mjs": getTscModuleResolutionAlternateResultMjs("foo2"),
+ "/home/src/projects/project/node_modules/foo2/index.d.ts": getTscModuleResolutionAlternateResultDts("foo2"),
+ "/home/src/projects/project/index.mts": stringtestutil.Dedent(`
+ import { foo } from "foo";
+ import { bar } from "bar";
+ import { foo2 } from "foo2";
+ import { bar2 } from "bar2";
+ `),
+ "/home/src/projects/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "node16",
+ "moduleResolution": "node16",
+ "traceResolution": true,
+ "incremental": true,
+ "strict": true,
+ "types": [],
+ },
+ "files": ["index.mts"],
+ }`),
+ },
+ cwd: "/home/src/projects/project",
+ edits: []*tscEdit{
+ {
+ caption: "delete the alternateResult in @types",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/projects/project/node_modules/@types/bar/index.d.ts")
+ },
+ // !!! repopulateInfo on diagnostics not yet implemented
+ expectedDiff: "Currently we arent repopulating error chain so errors will be different",
+ },
+ {
+ caption: "delete the node10Result in package/types",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/projects/project/node_modules/foo/index.d.ts")
+ },
+ // !!! repopulateInfo on diagnostics not yet implemented
+ expectedDiff: "Currently we arent repopulating error chain so errors will be different",
+ },
+ {
+ caption: "add the alternateResult in @types",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/@types/bar/index.d.ts", getTscModuleResolutionAlternateResultDts("bar"), false)
+ },
+ // !!! repopulateInfo on diagnostics not yet implemented
+ expectedDiff: "Currently we arent repopulating error chain so errors will be different",
+ },
+ {
+ caption: "add the alternateResult in package/types",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/foo/index.d.ts", getTscModuleResolutionAlternateResultDts("foo"), false)
+ },
+ },
+ {
+ caption: "update package.json from @types so error is fixed",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/@types/bar/package.json", getTscModuleResolutionAlternateResultAtTypesPackageJson("bar" /*addTypesCondition*/, true), false)
+ },
+ },
+ {
+ caption: "update package.json so error is fixed",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/foo/package.json", getTscModuleResolutionAlternateResultPackageJson("foo" /*addTypes*/, true /*addTypesCondition*/, true), false)
+ },
+ },
+ {
+ caption: "update package.json from @types so error is introduced",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/@types/bar2/package.json", getTscModuleResolutionAlternateResultAtTypesPackageJson("bar2" /*addTypesCondition*/, false), false)
+ },
+ },
+ {
+ caption: "update package.json so error is introduced",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/foo2/package.json", getTscModuleResolutionAlternateResultPackageJson("foo2" /*addTypes*/, true /*addTypesCondition*/, false), false)
+ },
+ },
+ {
+ caption: "delete the alternateResult in @types",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/projects/project/node_modules/@types/bar2/index.d.ts")
+ },
+ // !!! repopulateInfo on diagnostics not yet implemented
+ expectedDiff: "Currently we arent repopulating error chain so errors will be different",
+ },
+ {
+ caption: "delete the node10Result in package/types",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/projects/project/node_modules/foo2/index.d.ts")
+ },
+ // !!! repopulateInfo on diagnostics not yet implemented
+ expectedDiff: "Currently we arent repopulating error chain so errors will be different",
+ },
+ {
+ caption: "add the alternateResult in @types",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/@types/bar2/index.d.ts", getTscModuleResolutionAlternateResultDts("bar2"), false)
+ },
+ // !!! repopulateInfo on diagnostics not yet implemented
+ expectedDiff: "Currently we arent repopulating error chain so errors will be different",
+ },
+ {
+ caption: "add the ndoe10Result in package/types",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/node_modules/foo2/index.d.ts", getTscModuleResolutionAlternateResultDts("foo2"), false)
+ },
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "moduleResolution")
+ }
+}
+
+func TestTscNoCheck(t *testing.T) {
+ t.Parallel()
+ type noCheckScenario struct {
+ subScenario string
+ aText string
+ }
+ getTscNoCheckTestCase := func(scenario *noCheckScenario, incremental bool, commandLineArgs []string) *tscInput {
+ noChangeWithCheck := &tscEdit{
+ caption: "No Change run with checking",
+ commandLineArgs: commandLineArgs,
+ }
+ fixErrorNoCheck := &tscEdit{
+ caption: "Fix `a` error with noCheck",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/workspaces/project/a.ts", `export const a = "hello";`, false)
+ },
+ }
+ addErrorNoCheck := &tscEdit{
+ caption: "Introduce error with noCheck",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/workspaces/project/a.ts", scenario.aText, false)
+ },
+ }
+ return &tscInput{
+ subScenario: scenario.subScenario + core.IfElse(incremental, " with incremental", ""),
+ files: FileMap{
+ "/home/src/workspaces/project/a.ts": scenario.aText,
+ "/home/src/workspaces/project/b.ts": `export const b = 10;`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "declaration": true,
+ "incremental": %t
+ }
+ }`, incremental)),
+ },
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noCheck"}),
+ edits: []*tscEdit{
+ noChange,
+ fixErrorNoCheck, // Fix error with noCheck
+ noChange, // Should be no op
+ noChangeWithCheck, // Check errors - should not report any errors - update buildInfo
+ noChangeWithCheck, // Should be no op
+ noChange, // Should be no op
+ addErrorNoCheck,
+ noChange, // Should be no op
+ noChangeWithCheck, // Should check errors and update buildInfo
+ fixErrorNoCheck, // Fix error with noCheck
+ noChangeWithCheck, // Should check errors and update buildInfo
+ {
+ caption: "Add file with error",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/workspaces/project/c.ts", `export const c: number = "hello";`, false)
+ },
+ commandLineArgs: commandLineArgs,
+ },
+ addErrorNoCheck,
+ fixErrorNoCheck,
+ noChangeWithCheck,
+ noChange, // Should be no op
+ noChangeWithCheck, // Should be no op
+ },
+ }
+ }
+
+ cases := []noCheckScenario{
+ {"syntax errors", `export const a = "hello`},
+ {"semantic errors", `export const a: number = "hello";`},
+ {"dts errors", `export const a = class { private p = 10; };`},
+ }
+ testCases := core.FlatMap(cases, func(c noCheckScenario) []*tscInput {
+ return []*tscInput{
+ getTscNoCheckTestCase(&c, false, []string{}),
+ getTscNoCheckTestCase(&c, true, []string{}),
+ getTscNoCheckTestCase(&c, false, []string{"-b", "-v"}),
+ getTscNoCheckTestCase(&c, true, []string{"-b", "-v"}),
+ }
+ })
+ for _, test := range testCases {
+ test.run(t, "noCheck")
+ }
+}
+
+func TestTscNoEmit(t *testing.T) {
+ t.Parallel()
+ type tscNoEmitScenario struct {
+ subScenario string
+ aText string
+ dtsEnabled bool
+ }
+ noEmitScenarios := []*tscNoEmitScenario{
+ {
+ subScenario: "syntax errors",
+ aText: `const a = "hello`,
+ },
+ {
+ subScenario: "semantic errors",
+ aText: `const a: number = "hello"`,
+ },
+ {
+ subScenario: "dts errors",
+ aText: `const a = class { private p = 10; };`,
+ dtsEnabled: true,
+ },
+ {
+ subScenario: "dts errors without dts enabled",
+ aText: `const a = class { private p = 10; };`,
+ },
+ }
+ getTscNoEmitAndErrorsFileMap := func(scenario *tscNoEmitScenario, incremental bool, asModules bool) FileMap {
+ files := FileMap{
+ "/home/src/projects/project/a.ts": core.IfElse(asModules, `export `, "") + scenario.aText,
+ "/home/src/projects/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "incremental": %t,
+ "declaration": %t
+ }
+ }
+ `, incremental, scenario.dtsEnabled)),
+ }
+ if asModules {
+ files["/home/src/projects/project/b.ts"] = `export const b = 10;`
+ }
+ return files
+ }
+ getTscNoEmitAndErrorsEdits := func(scenario *tscNoEmitScenario, commandLineArgs []string, asModules bool) []*tscEdit {
+ fixedATsContent := core.IfElse(asModules, "export ", "") + `const a = "hello";`
+ return []*tscEdit{
+ noChange,
+ {
+ caption: "Fix error",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/a.ts", fixedATsContent, false)
+ },
+ },
+ noChange,
+ {
+ caption: "Emit after fixing error",
+ commandLineArgs: commandLineArgs,
+ },
+ noChange,
+ {
+ caption: "Introduce error",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/projects/project/a.ts", scenario.aText, false)
+ },
+ },
+ {
+ caption: "Emit when error",
+ commandLineArgs: commandLineArgs,
+ },
+ noChange,
+ }
+ }
+ getTscNoEmitAndErrorsTestCases := func(scenarios []*tscNoEmitScenario, commandLineArgs []string) []*tscInput {
+ testingCases := make([]*tscInput, 0, len(scenarios)*3)
+ for _, scenario := range scenarios {
+ testingCases = append(
+ testingCases,
+ &tscInput{
+ subScenario: scenario.subScenario,
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit"}),
+ files: getTscNoEmitAndErrorsFileMap(scenario, false, false),
+ cwd: "/home/src/projects/project",
+ edits: getTscNoEmitAndErrorsEdits(scenario, commandLineArgs, false),
+ },
+ &tscInput{
+ subScenario: scenario.subScenario + " with incremental",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit"}),
+ files: getTscNoEmitAndErrorsFileMap(scenario, true, false),
+ cwd: "/home/src/projects/project",
+ edits: getTscNoEmitAndErrorsEdits(scenario, commandLineArgs, false),
+ },
+ &tscInput{
+ subScenario: scenario.subScenario + " with incremental as modules",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit"}),
+ files: getTscNoEmitAndErrorsFileMap(scenario, true, true),
+ cwd: "/home/src/projects/project",
+ edits: getTscNoEmitAndErrorsEdits(scenario, commandLineArgs, true),
+ },
+ )
+ }
+ return testingCases
+ }
+ getTscNoEmitChangesFileMap := func(optionsStr string) FileMap {
+ return FileMap{
+ "/home/src/workspaces/project/src/class.ts": stringtestutil.Dedent(`
+ export class classC {
+ prop = 1;
+ }`),
+ "/home/src/workspaces/project/src/indirectClass.ts": stringtestutil.Dedent(`
+ import { classC } from './class';
+ export class indirectClass {
+ classC = new classC();
+ }`),
+ "/home/src/workspaces/project/src/directUse.ts": stringtestutil.Dedent(`
+ import { indirectClass } from './indirectClass';
+ new indirectClass().classC.prop;`),
+ "/home/src/workspaces/project/src/indirectUse.ts": stringtestutil.Dedent(`
+ import { indirectClass } from './indirectClass';
+ new indirectClass().classC.prop;`),
+ "/home/src/workspaces/project/src/noChangeFile.ts": stringtestutil.Dedent(`
+ export function writeLog(s: string) {
+ }`),
+ "/home/src/workspaces/project/src/noChangeFileWithEmitSpecificError.ts": stringtestutil.Dedent(`
+ function someFunc(arguments: boolean, ...rest: any[]) {
+ }`),
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": { %s }
+ }`, optionsStr)),
+ }
+ }
+
+ type tscNoEmitChangesScenario struct {
+ subScenario string
+ optionsString string
+ }
+ noEmitChangesScenarios := []*tscNoEmitChangesScenario{
+ {
+ // !!! sheetal missing initial reporting of Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters is absent
+ subScenario: "composite",
+ optionsString: `"composite": true`,
+ },
+ {
+ subScenario: "incremental declaration",
+ optionsString: `"incremental": true, "declaration": true`,
+ },
+ {
+ subScenario: "incremental",
+ optionsString: `"incremental": true`,
+ },
+ }
+ getTscNoEmitChangesTestCases := func(scenarios []*tscNoEmitChangesScenario, commandLineArgs []string) []*tscInput {
+ noChangeWithNoEmit := &tscEdit{
+ caption: "No Change run with noEmit",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit"}),
+ }
+ noChangeWithEmit := &tscEdit{
+ caption: "No Change run with emit",
+ commandLineArgs: commandLineArgs,
+ }
+ introduceError := func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop", "prop1")
+ }
+ fixError := func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop1", "prop")
+ }
+ testCases := make([]*tscInput, 0, len(scenarios))
+ for _, scenario := range scenarios {
+ testCases = append(
+ testCases,
+ &tscInput{
+ subScenario: "changes " + scenario.subScenario,
+ commandLineArgs: commandLineArgs,
+ files: getTscNoEmitChangesFileMap(scenario.optionsString),
+ edits: []*tscEdit{
+ noChangeWithNoEmit,
+ noChangeWithNoEmit,
+ {
+ caption: "Introduce error but still noEmit",
+ commandLineArgs: noChangeWithNoEmit.commandLineArgs,
+ edit: introduceError,
+ },
+ {
+ caption: "Fix error and emit",
+ edit: fixError,
+ },
+ noChangeWithEmit,
+ noChangeWithNoEmit,
+ noChangeWithNoEmit,
+ noChangeWithEmit,
+ {
+ caption: "Introduce error and emit",
+ edit: introduceError,
+ },
+ noChangeWithEmit,
+ noChangeWithNoEmit,
+ noChangeWithNoEmit,
+ noChangeWithEmit,
+ {
+ caption: "Fix error and no emit",
+ commandLineArgs: noChangeWithNoEmit.commandLineArgs,
+ edit: fixError,
+ },
+ noChangeWithEmit,
+ noChangeWithNoEmit,
+ noChangeWithNoEmit,
+ noChangeWithEmit,
+ },
+ },
+ &tscInput{
+ subScenario: "changes with initial noEmit " + scenario.subScenario,
+ commandLineArgs: noChangeWithNoEmit.commandLineArgs,
+ files: getTscNoEmitChangesFileMap(scenario.optionsString),
+ edits: []*tscEdit{
+ noChangeWithEmit,
+ {
+ caption: "Introduce error with emit",
+ commandLineArgs: commandLineArgs,
+ edit: introduceError,
+ },
+ {
+ caption: "Fix error and no emit",
+ edit: fixError,
+ },
+ noChangeWithEmit,
+ },
+ },
+ )
+ }
+ return testCases
+ }
+ getTscNoEmitDtsChangesFileMap := func(incremental bool, asModules bool) FileMap {
+ files := FileMap{
+ "/home/src/projects/project/a.ts": core.IfElse(asModules, `export const a = class { private p = 10; };`, `const a = class { private p = 10; };`),
+ "/home/src/projects/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "incremental": %t,
+ }
+ }
+ `, incremental)),
+ }
+ if asModules {
+ files["/home/src/projects/project/b.ts"] = `export const b = 10;`
+ }
+ return files
+ }
+ getTscNoEmitDtsChangesEdits := func(commandLineArgs []string) []*tscEdit {
+ return []*tscEdit{
+ noChange,
+ {
+ caption: "With declaration enabled noEmit - Should report errors",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit", "--declaration"}),
+ },
+ {
+ caption: "With declaration and declarationMap noEmit - Should report errors",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit", "--declaration", "--declarationMap"}),
+ },
+ noChange,
+ {
+ caption: "Dts Emit with error",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--declaration"}),
+ },
+ {
+ caption: "Fix the error",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/projects/project/a.ts", "private", "public")
+ },
+ },
+ {
+ caption: "With declaration enabled noEmit",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit", "--declaration"}),
+ },
+ {
+ caption: "With declaration and declarationMap noEmit",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit", "--declaration", "--declarationMap"}),
+ },
+ }
+ }
+ getTscNoEmitDtsChangesTestCases := func() []*tscInput {
+ return []*tscInput{
+ {
+ subScenario: "dts errors with declaration enable changes",
+ commandLineArgs: []string{"-b", "-v", "--noEmit"},
+ files: getTscNoEmitDtsChangesFileMap(false, false),
+ cwd: "/home/src/projects/project",
+ edits: getTscNoEmitDtsChangesEdits([]string{"-b", "-v"}),
+ },
+ {
+ subScenario: "dts errors with declaration enable changes with incremental",
+ commandLineArgs: []string{"-b", "-v", "--noEmit"},
+ files: getTscNoEmitDtsChangesFileMap(true, false),
+ cwd: "/home/src/projects/project",
+ edits: getTscNoEmitDtsChangesEdits([]string{"-b", "-v"}),
+ },
+ {
+ subScenario: "dts errors with declaration enable changes with incremental as modules",
+ commandLineArgs: []string{"-b", "-v", "--noEmit"},
+ files: getTscNoEmitDtsChangesFileMap(true, true),
+ cwd: "/home/src/projects/project",
+ edits: getTscNoEmitDtsChangesEdits([]string{"-b", "-v"}),
+ },
+ }
+ }
+ getTscNoEmitDtsChangesMultiFileErrorsTestCases := func(commandLineArgs []string) []*tscInput {
+ aContent := `export const a = class { private p = 10; };`
+ return []*tscInput{
+ {
+ subScenario: "dts errors with declaration enable changes with multiple files",
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit"}),
+ files: FileMap{
+ "/home/src/projects/project/a.ts": aContent,
+ "/home/src/projects/project/b.ts": `export const b = 10;`,
+ "/home/src/projects/project/c.ts": strings.Replace(aContent, "a", "c", 1),
+ "/home/src/projects/project/d.ts": strings.Replace(aContent, "a", "d", 1),
+ "/home/src/projects/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ }
+ }
+ `),
+ },
+ cwd: "/home/src/projects/project",
+ edits: slices.Concat(
+ getTscNoEmitDtsChangesEdits(commandLineArgs),
+ []*tscEdit{
+ {
+ caption: "Fix the another ",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/projects/project/c.ts", "private", "public")
+ },
+ commandLineArgs: slices.Concat(commandLineArgs, []string{"--noEmit", "--declaration", "--declarationMap"}),
+ },
+ },
+ ),
+ },
+ }
+ }
+
+ testCases := slices.Concat(
+ []*tscInput{
+ {
+ subScenario: "when project has strict true",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "strict": true
+ }
+ }`),
+ "/home/src/workspaces/project/class1.ts": `export class class1 {}`,
+ },
+ commandLineArgs: []string{"--noEmit"},
+ edits: noChangeOnlyEdit,
+ },
+ },
+ getTscNoEmitAndErrorsTestCases(noEmitScenarios, []string{}),
+ getTscNoEmitAndErrorsTestCases(noEmitScenarios, []string{"-b", "-v"}),
+ getTscNoEmitChangesTestCases(noEmitChangesScenarios, []string{}),
+ getTscNoEmitChangesTestCases(noEmitChangesScenarios, []string{"-b", "-v"}),
+ getTscNoEmitDtsChangesTestCases(),
+ getTscNoEmitDtsChangesMultiFileErrorsTestCases([]string{}),
+ getTscNoEmitDtsChangesMultiFileErrorsTestCases([]string{"-b", "-v"}),
+ )
+
+ for _, test := range testCases {
+ test.run(t, "noEmit")
+ }
+}
+
+func TestTscNoEmitOnError(t *testing.T) {
+ t.Parallel()
+ type tscNoEmitOnErrorScenario struct {
+ subScenario string
+ mainErrorContent string
+ fixedErrorContent string
+ }
+ getTscNoEmitOnErrorFileMap := func(scenario *tscNoEmitOnErrorScenario, declaration bool, incremental bool) FileMap {
+ return FileMap{
+ "/user/username/projects/noEmitOnError/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "outDir": "./dev-build",
+ "declaration": %t,
+ "incremental": %t,
+ "noEmitOnError": true,
+ },
+ }`, declaration, incremental)),
+ "/user/username/projects/noEmitOnError/shared/types/db.ts": stringtestutil.Dedent(`
+ export interface A {
+ name: string;
+ }
+ `),
+ "/user/username/projects/noEmitOnError/src/main.ts": scenario.mainErrorContent,
+ "/user/username/projects/noEmitOnError/src/other.ts": stringtestutil.Dedent(`
+ console.log("hi");
+ export { }
+ `),
+ }
+ }
+ getTscNoEmitOnErrorTestCases := func(scenarios []*tscNoEmitOnErrorScenario, commandLineArgs []string) []*tscInput {
+ testCases := make([]*tscInput, 0, len(scenarios)*4)
+ for _, scenario := range scenarios {
+ edits := []*tscEdit{
+ noChange,
+ {
+ caption: "Fix error",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/user/username/projects/noEmitOnError/src/main.ts", scenario.fixedErrorContent, false)
+ },
+ },
+ noChange,
+ }
+ testCases = append(
+ testCases,
+ &tscInput{
+ subScenario: scenario.subScenario,
+ files: getTscNoEmitOnErrorFileMap(scenario, false, false),
+ cwd: "/user/username/projects/noEmitOnError",
+ commandLineArgs: commandLineArgs,
+ edits: edits,
+ },
+ &tscInput{
+ subScenario: scenario.subScenario + " with declaration",
+ files: getTscNoEmitOnErrorFileMap(scenario, true, false),
+ cwd: "/user/username/projects/noEmitOnError",
+ commandLineArgs: commandLineArgs,
+ edits: edits,
+ },
+ &tscInput{
+ subScenario: scenario.subScenario + " with incremental",
+ files: getTscNoEmitOnErrorFileMap(scenario, false, true),
+ cwd: "/user/username/projects/noEmitOnError",
+ commandLineArgs: commandLineArgs,
+ edits: edits,
+ },
+ &tscInput{
+ subScenario: scenario.subScenario + " with declaration with incremental",
+ files: getTscNoEmitOnErrorFileMap(scenario, true, true),
+ cwd: "/user/username/projects/noEmitOnError",
+ commandLineArgs: commandLineArgs,
+ edits: edits,
+ },
+ )
+ }
+ return testCases
+ }
+ scenarios := []*tscNoEmitOnErrorScenario{
+ {
+ subScenario: "syntax errors",
+ mainErrorContent: stringtestutil.Dedent(`
+ import { A } from "../shared/types/db";
+ const a = {
+ lastName: 'sdsd'
+ ;
+ `),
+ fixedErrorContent: stringtestutil.Dedent(`
+ import { A } from "../shared/types/db";
+ const a = {
+ lastName: 'sdsd'
+ };`),
+ },
+ {
+ subScenario: "semantic errors",
+ mainErrorContent: stringtestutil.Dedent(`
+ import { A } from "../shared/types/db";
+ const a: string = 10;`),
+ fixedErrorContent: stringtestutil.Dedent(`
+ import { A } from "../shared/types/db";
+ const a: string = "hello";`),
+ },
+ {
+ subScenario: "dts errors",
+ mainErrorContent: stringtestutil.Dedent(`
+ import { A } from "../shared/types/db";
+ export const a = class { private p = 10; };
+ `),
+ fixedErrorContent: stringtestutil.Dedent(`
+ import { A } from "../shared/types/db";
+ export const a = class { p = 10; };
+ `),
+ },
+ }
+ testCases := slices.Concat(
+ getTscNoEmitOnErrorTestCases(scenarios, []string{}),
+ getTscNoEmitOnErrorTestCases(scenarios, []string{"-b", "-v"}),
+ []*tscInput{
+ {
+ subScenario: `when declarationMap changes`,
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "noEmitOnError": true,
+ "declaration": true,
+ "composite": true,
+ },
+ }`),
+ "/home/src/workspaces/project/a.ts": "const x = 10;",
+ "/home/src/workspaces/project/b.ts": "const y = 10;",
+ },
+ edits: []*tscEdit{
+ {
+ caption: "error and enable declarationMap",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/a.ts", "x", "x: 20")
+ },
+ commandLineArgs: []string{"--declarationMap"},
+ },
+ {
+ caption: "fix error declarationMap",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/a.ts", "x: 20", "x")
+ },
+ commandLineArgs: []string{"--declarationMap"},
+ },
+ },
+ },
+ {
+ subScenario: "file deleted before fixing error with noEmitOnError",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "outDir": "outDir",
+ "noEmitOnError": true,
+ },
+ }`),
+ "/home/src/workspaces/project/file1.ts": `export const x: 30 = "hello";`,
+ "/home/src/workspaces/project/file2.ts": `export class D { }`,
+ },
+ commandLineArgs: []string{"-i"},
+ edits: []*tscEdit{
+ {
+ caption: "delete file without error",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/project/file2.ts")
+ },
+ },
+ },
+ },
+ },
+ )
+
+ for _, test := range testCases {
+ test.run(t, "noEmitOnError")
+ }
+}
+
+func TestTscProjectReferences(t *testing.T) {
+ t.Parallel()
+ cases := []tscInput{
+ {
+ subScenario: "when project references composite project with noEmit",
+ files: FileMap{
+ "/home/src/workspaces/solution/utils/index.ts": "export const x = 10;",
+ "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "noEmit": true
+ }
+ }`),
+ "/home/src/workspaces/solution/project/index.ts": `import { x } from "../utils";`,
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../utils" },
+ ],
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "project"},
+ },
+ {
+ subScenario: "when project references composite",
+ files: FileMap{
+ "/home/src/workspaces/solution/utils/index.ts": "export const x = 10;",
+ "/home/src/workspaces/solution/utils/index.d.ts": "export declare const x = 10;",
+ "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true
+ }
+ }`),
+ "/home/src/workspaces/solution/project/index.ts": `import { x } from "../utils";`,
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../utils" },
+ ],
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "project"},
+ },
+ {
+ subScenario: "when project reference is not built",
+ files: FileMap{
+ "/home/src/workspaces/solution/utils/index.ts": "export const x = 10;",
+ "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true
+ }
+ }`),
+ "/home/src/workspaces/solution/project/index.ts": `import { x } from "../utils";`,
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../utils" },
+ ],
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "project"},
+ },
+ {
+ subScenario: "when project contains invalid project reference",
+ files: FileMap{
+ "/home/src/workspaces/solution/project/index.ts": `export const x = 10;`,
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../utils" },
+ ],
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "project"},
+ },
+ {
+ subScenario: "default import interop uses referenced project settings",
+ files: FileMap{
+ "/home/src/workspaces/project/node_modules/ambiguous-package/package.json": stringtestutil.Dedent(`
+ {
+ "name": "ambiguous-package"
+ }`),
+ "/home/src/workspaces/project/node_modules/ambiguous-package/index.d.ts": "export declare const ambiguous: number;",
+ "/home/src/workspaces/project/node_modules/esm-package/package.json": stringtestutil.Dedent(`
+ {
+ "name": "esm-package",
+ "type": "module"
+ }`),
+ "/home/src/workspaces/project/node_modules/esm-package/index.d.ts": "export declare const esm: number;",
+ "/home/src/workspaces/project/lib/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "rootDir": "src",
+ "outDir": "dist",
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ },
+ "include": ["src"],
+ }`),
+ "/home/src/workspaces/project/lib/src/a.ts": "export const a = 0;",
+ "/home/src/workspaces/project/lib/dist/a.d.ts": "export declare const a = 0;",
+ "/home/src/workspaces/project/app/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "rootDir": "src",
+ "outDir": "dist",
+ },
+ "include": ["src"],
+ "references": [
+ { "path": "../lib" },
+ ],
+ }`),
+ "/home/src/workspaces/project/app/src/local.ts": "export const local = 0;",
+ "/home/src/workspaces/project/app/src/index.ts": stringtestutil.Dedent(`
+ import local from "./local"; // Error
+ import esm from "esm-package"; // Error
+ import referencedSource from "../../lib/src/a"; // Error
+ import referencedDeclaration from "../../lib/dist/a"; // Error
+ import ambiguous from "ambiguous-package"; // Ok`),
+ },
+ commandLineArgs: []string{"--p", "app", "--pretty", "false"},
+ },
+ {
+ subScenario: "referencing ambient const enum from referenced project with preserveConstEnums",
+ files: FileMap{
+ "/home/src/workspaces/solution/utils/index.ts": "export const enum E { A = 1 }",
+ "/home/src/workspaces/solution/utils/index.d.ts": "export declare const enum E { A = 1 }",
+ "/home/src/workspaces/solution/utils/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "preserveConstEnums": true,
+ },
+ }`),
+ "/home/src/workspaces/solution/project/index.ts": `import { E } from "../utils"; E.A;`,
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "isolatedModules": true,
+ },
+ "references": [
+ { "path": "../utils" },
+ ],
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "project"},
+ },
+ {
+ subScenario: "importing const enum from referenced project with preserveConstEnums and verbatimModuleSyntax",
+ files: FileMap{
+ "/home/src/workspaces/solution/preserve/index.ts": "export const enum E { A = 1 }",
+ "/home/src/workspaces/solution/preserve/index.d.ts": "export declare const enum E { A = 1 }",
+ "/home/src/workspaces/solution/preserve/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "preserveConstEnums": true,
+ },
+ }`),
+ "/home/src/workspaces/solution/no-preserve/index.ts": "export const enum E { A = 1 }",
+ "/home/src/workspaces/solution/no-preserve/index.d.ts": "export declare const enum F { A = 1 }",
+ "/home/src/workspaces/solution/no-preserve/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "preserveConstEnums": false,
+ },
+ }`),
+ "/home/src/workspaces/solution/project/index.ts": stringtestutil.Dedent(`
+ import { E } from "../preserve";
+ import { F } from "../no-preserve";
+ E.A;
+ F.A;`),
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "preserve",
+ "verbatimModuleSyntax": true,
+ },
+ "references": [
+ { "path": "../preserve" },
+ { "path": "../no-preserve" },
+ ],
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "project", "--pretty", "false"},
+ },
+ {
+ subScenario: "rewriteRelativeImportExtensionsProjectReferences1",
+ files: FileMap{
+ "/home/src/workspaces/packages/common/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "rootDir": "src",
+ "outDir": "dist",
+ "module": "nodenext"
+ }
+ }`),
+ "/home/src/workspaces/packages/common/package.json": stringtestutil.Dedent(`
+ {
+ "name": "common",
+ "version": "1.0.0",
+ "type": "module",
+ "exports": {
+ ".": {
+ "source": "./src/index.ts",
+ "default": "./dist/index.js"
+ }
+ }
+ }`),
+ "/home/src/workspaces/packages/common/src/index.ts": "export {};",
+ "/home/src/workspaces/packages/common/dist/index.d.ts": "export {};",
+ "/home/src/workspaces/packages/main/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "nodenext",
+ "rewriteRelativeImportExtensions": true,
+ "rootDir": "src",
+ "outDir": "dist"
+ },
+ "references": [
+ { "path": "../common" }
+ ]
+ }`),
+ "/home/src/workspaces/packages/main/package.json": stringtestutil.Dedent(`
+ {
+ "type": "module"
+ }`),
+ "/home/src/workspaces/packages/main/src/index.ts": `import {} from "../../common/src/index.ts";`,
+ },
+ cwd: "/home/src/workspaces",
+ commandLineArgs: []string{"-p", "packages/main", "--pretty", "false"},
+ },
+ {
+ subScenario: "rewriteRelativeImportExtensionsProjectReferences2",
+ files: FileMap{
+ "/home/src/workspaces/solution/src/tsconfig-base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "nodenext",
+ "composite": true,
+ "rootDir": ".",
+ "outDir": "../dist",
+ "rewriteRelativeImportExtensions": true
+ }
+ }`),
+ "/home/src/workspaces/solution/src/compiler/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {}
+ }`),
+ "/home/src/workspaces/solution/src/compiler/parser.ts": "export {};",
+ "/home/src/workspaces/solution/dist/compiler/parser.d.ts": "export {};",
+ "/home/src/workspaces/solution/src/services/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {},
+ "references": [
+ { "path": "../compiler" }
+ ]
+ }`),
+ "/home/src/workspaces/solution/src/services/services.ts": `import {} from "../compiler/parser.ts";`,
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "src/services", "--pretty", "false"},
+ },
+ {
+ subScenario: "rewriteRelativeImportExtensionsProjectReferences3",
+ files: FileMap{
+ "/home/src/workspaces/solution/src/tsconfig-base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "module": "nodenext",
+ "composite": true,
+ "rewriteRelativeImportExtensions": true
+ }
+ }`),
+ "/home/src/workspaces/solution/src/compiler/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "rootDir": ".",
+ "outDir": "../../dist/compiler"
+ }
+ }`),
+ "/home/src/workspaces/solution/src/compiler/parser.ts": "export {};",
+ "/home/src/workspaces/solution/dist/compiler/parser.d.ts": "export {};",
+ "/home/src/workspaces/solution/src/services/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "rootDir": ".",
+ "outDir": "../../dist/services"
+ },
+ "references": [
+ { "path": "../compiler" }
+ ]
+ }`),
+ "/home/src/workspaces/solution/src/services/services.ts": `import {} from "../compiler/parser.ts";`,
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--p", "src/services", "--pretty", "false"},
+ },
+ {
+ subScenario: "default setup was created correctly",
+ files: FileMap{
+ "/home/src/workspaces/project/primary/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ }
+ }`),
+ "/home/src/workspaces/project/primary/a.ts": "export { };",
+ "/home/src/workspaces/project/secondary/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "references": [{
+ "path": "../primary"
+ }]
+ }`),
+ "/home/src/workspaces/project/secondary/b.ts": `import * as mod_1 from "../primary/a";`,
+ },
+ commandLineArgs: []string{"--p", "primary/tsconfig.json"},
+ },
+ {
+ subScenario: "errors when declaration = false",
+ files: FileMap{
+ "/home/src/workspaces/project/primary/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ "declaration": false
+ }
+ }`),
+ "/home/src/workspaces/project/primary/a.ts": "export { };",
+ },
+ commandLineArgs: []string{"--p", "primary/tsconfig.json"},
+ },
+ {
+ subScenario: "errors when the referenced project doesnt have composite",
+ files: FileMap{
+ "/home/src/workspaces/project/primary/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": false,
+ "outDir": "bin",
+ }
+ }`),
+ "/home/src/workspaces/project/primary/a.ts": "export { };",
+ "/home/src/workspaces/project/reference/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "files": [ "b.ts" ],
+ "references": [ { "path": "../primary" } ]
+ }`),
+ "/home/src/workspaces/project/reference/b.ts": `import * as mod_1 from "../primary/a";`,
+ },
+ commandLineArgs: []string{"--p", "reference/tsconfig.json"},
+ },
+ {
+ subScenario: "does not error when the referenced project doesnt have composite if its a container project",
+ files: FileMap{
+ "/home/src/workspaces/project/primary/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": false,
+ "outDir": "bin",
+ }
+ }`),
+ "/home/src/workspaces/project/primary/a.ts": "export { };",
+ "/home/src/workspaces/project/reference/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "files": [ ],
+ "references": [{
+ "path": "../primary"
+ }]
+ }`),
+ "/home/src/workspaces/project/reference/b.ts": `import * as mod_1 from "../primary/a";`,
+ },
+ commandLineArgs: []string{"--p", "reference/tsconfig.json"},
+ },
+ {
+ subScenario: "errors when the file list is not exhaustive",
+ files: FileMap{
+ "/home/src/workspaces/project/primary/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "files": [ "a.ts" ]
+ }`),
+ "/home/src/workspaces/project/primary/a.ts": "import * as b from './b'",
+ "/home/src/workspaces/project/primary/b.ts": "export {}",
+ },
+ commandLineArgs: []string{"--p", "primary/tsconfig.json"},
+ },
+ {
+ subScenario: "errors when the referenced project doesnt exist",
+ files: FileMap{
+ "/home/src/workspaces/project/primary/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "references": [{
+ "path": "../foo"
+ }]
+ }`),
+ "/home/src/workspaces/project/primary/a.ts": "export { };",
+ },
+ commandLineArgs: []string{"--p", "primary/tsconfig.json"},
+ },
+ {
+ subScenario: "redirects to the output dts file",
+ files: FileMap{
+ "/home/src/workspaces/project/alpha/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ }
+ }`),
+ "/home/src/workspaces/project/alpha/a.ts": "export const m: number = 3;",
+ "/home/src/workspaces/project/alpha/bin/a.d.ts": "export { };",
+ "/home/src/workspaces/project/beta/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "references": [ { "path": "../alpha" } ]
+ }`),
+ "/home/src/workspaces/project/beta/b.ts": "import { m } from '../alpha/a'",
+ },
+ commandLineArgs: []string{"--p", "beta/tsconfig.json", "--explainFiles"},
+ },
+ {
+ subScenario: "issues a nice error when the input file is missing",
+ files: FileMap{
+ "/home/src/workspaces/project/alpha/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "references": []
+ }`),
+ "/home/src/workspaces/project/alpha/a.ts": "export const m: number = 3;",
+ "/home/src/workspaces/project/beta/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "references": [ { "path": "../alpha" } ]
+ }`),
+ "/home/src/workspaces/project/beta/b.ts": "import { m } from '../alpha/a'",
+ },
+ commandLineArgs: []string{"--p", "beta/tsconfig.json"},
+ },
+ {
+ subScenario: "issues a nice error when the input file is missing when module reference is not relative",
+ files: FileMap{
+ "/home/src/workspaces/project/alpha/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ }
+ }`),
+ "/home/src/workspaces/project/alpha/a.ts": "export const m: number = 3;",
+ "/home/src/workspaces/project/beta/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ "paths": {
+ "@alpha/*": ["../alpha/*"],
+ },
+ },
+ "references": [ { "path": "../alpha" } ]
+ }`),
+ "/home/src/workspaces/project/beta/b.ts": "import { m } from '@alpha/a'",
+ },
+ commandLineArgs: []string{"--p", "beta/tsconfig.json"},
+ },
+ {
+ subScenario: "doesnt infer the rootDir from source paths",
+ files: FileMap{
+ "/home/src/workspaces/project/alpha/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "references": []
+ }`),
+ "/home/src/workspaces/project/alpha/src/a.ts": "export const m: number = 3;",
+ },
+ commandLineArgs: []string{"--p", "alpha/tsconfig.json"},
+ },
+ {
+ // !!! sheetal rootDir error not reported
+ subScenario: "errors when a file is outside the rootdir",
+ files: FileMap{
+ "/home/src/workspaces/project/alpha/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "outDir": "bin",
+ },
+ "references": []
+ }`),
+ "/home/src/workspaces/project/alpha/src/a.ts": "import * as b from '../../beta/b'",
+ "/home/src/workspaces/project/beta/b.ts": "export { }",
+ },
+ commandLineArgs: []string{"--p", "alpha/tsconfig.json"},
+ },
+ }
+
+ for _, c := range cases {
+ c.run(t, "projectReferences")
+ }
+}
+
+func TestTypeAcquisition(t *testing.T) {
+ t.Parallel()
+ (&tscInput{
+ subScenario: "parse tsconfig with typeAcquisition",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "noEmit": true,
+ },
+ "typeAcquisition": {
+ "enable": true,
+ "include": ["0.d.ts", "1.d.ts"],
+ "exclude": ["0.js", "1.js"],
+ "disableFilenameBasedTypeAcquisition": true,
+ },
+ }`),
+ },
+ commandLineArgs: []string{},
+ }).run(t, "typeAcquisition")
+}
diff --git a/internal/execute/tsctests/tscbuild_test.go b/internal/execute/tsctests/tscbuild_test.go
new file mode 100644
index 0000000000..7e11b25f58
--- /dev/null
+++ b/internal/execute/tsctests/tscbuild_test.go
@@ -0,0 +1,2937 @@
+package tsctests
+
+import (
+ "fmt"
+ "slices"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/testutil/harnessutil"
+ "github.com/microsoft/typescript-go/internal/testutil/stringtestutil"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/vfs/vfstest"
+ "gotest.tools/v3/assert"
+)
+
+func TestBuildCommandLine(t *testing.T) {
+ t.Parallel()
+ getBuildCommandLineDifferentOptionsMap := func(optionName string) FileMap {
+ return FileMap{
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "%s": true
+ }
+ }`, optionName)),
+ "/home/src/workspaces/project/a.ts": `export const a = 10;const aLocal = 10;`,
+ "/home/src/workspaces/project/b.ts": `export const b = 10;const bLocal = 10;`,
+ "/home/src/workspaces/project/c.ts": `import { a } from "./a";export const c = a;`,
+ "/home/src/workspaces/project/d.ts": `import { b } from "./b";export const d = b;`,
+ }
+ }
+ getBuildCommandLineEmitDeclarationOnlyMap := func(options []string) FileMap {
+ compilerOptionsStr := strings.Join(core.Map(options, func(opt string) string {
+ return fmt.Sprintf(`"%s": true`, opt)
+ }), ", ")
+ return FileMap{
+ "/home/src/workspaces/solution/project1/src/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": { %s }
+ }`, compilerOptionsStr)),
+ "/home/src/workspaces/solution/project1/src/a.ts": `export const a = 10;const aLocal = 10;`,
+ "/home/src/workspaces/solution/project1/src/b.ts": `export const b = 10;const bLocal = 10;`,
+ "/home/src/workspaces/solution/project1/src/c.ts": `import { a } from "./a";export const c = a;`,
+ "/home/src/workspaces/solution/project1/src/d.ts": `import { b } from "./b";export const d = b;`,
+ "/home/src/workspaces/solution/project2/src/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": { %s },
+ "references": [{ "path": "../../project1/src" }]
+ }`, compilerOptionsStr)),
+ "/home/src/workspaces/solution/project2/src/e.ts": `export const e = 10;`,
+ "/home/src/workspaces/solution/project2/src/f.ts": `import { a } from "../../project1/src/a"; export const f = a;`,
+ "/home/src/workspaces/solution/project2/src/g.ts": `import { b } from "../../project1/src/b"; export const g = b;`,
+ }
+ }
+ getBuildCommandLineEmitDeclarationOnlyTestCases := func(options []string, suffix string) []*tscInput {
+ return []*tscInput{
+ {
+ subScenario: "emitDeclarationOnly on commandline" + suffix,
+ files: getBuildCommandLineEmitDeclarationOnlyMap(options),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "project2/src", "--verbose", "--emitDeclarationOnly"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "local change",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "const aa = 10;")
+ },
+ },
+ {
+ caption: "non local change",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "export const aaa = 10;")
+ },
+ },
+ {
+ caption: "emit js files",
+ commandLineArgs: []string{"--b", "project2/src", "--verbose"},
+ },
+ noChange,
+ {
+ caption: "js emit with change without emitDeclarationOnly",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const alocal = 10;")
+ },
+ commandLineArgs: []string{"--b", "project2/src", "--verbose"},
+ },
+ {
+ caption: "local change",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const aaaa = 10;")
+ },
+ },
+ {
+ caption: "non local change",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "export const aaaaa = 10;")
+ },
+ },
+ {
+ caption: "js emit with change without emitDeclarationOnly",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "export const a2 = 10;")
+ },
+ commandLineArgs: []string{"--b", "project2/src", "--verbose"},
+ },
+ },
+ },
+ {
+ subScenario: "emitDeclarationOnly false on commandline" + suffix,
+ files: getBuildCommandLineEmitDeclarationOnlyMap(slices.Concat(options, []string{"emitDeclarationOnly"})),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "project2/src", "--verbose"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "change",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "const aa = 10;")
+ },
+ },
+ {
+ caption: "emit js files",
+ commandLineArgs: []string{"--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"},
+ },
+ noChange,
+ {
+ caption: "no change run with js emit",
+ commandLineArgs: []string{"--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"},
+ },
+ {
+ caption: "js emit with change",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const blocal = 10;")
+ },
+ commandLineArgs: []string{"--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"},
+ },
+ },
+ },
+ }
+ }
+ testCases := slices.Concat(
+ []*tscInput{
+ {
+ subScenario: "help",
+ files: FileMap{},
+ commandLineArgs: []string{"--build", "--help"},
+ },
+ {
+ subScenario: "different options",
+ files: getBuildCommandLineDifferentOptionsMap("composite"),
+ commandLineArgs: []string{"--build", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--build", "--verbose", "--sourceMap"},
+ },
+ {
+ caption: "should re-emit only js so they dont contain sourcemap",
+ },
+ {
+ caption: "with declaration should not emit anything",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration"},
+ },
+ noChange,
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration", "--declarationMap"},
+ },
+ {
+ caption: "should re-emit only dts so they dont contain sourcemap",
+ },
+ {
+ caption: "with emitDeclarationOnly should not emit anything",
+ commandLineArgs: []string{"--build", "--verbose", "--emitDeclarationOnly"},
+ },
+ noChange,
+ {
+ caption: "local change",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10")
+ },
+ },
+ {
+ caption: "with declaration should not emit anything",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration"},
+ },
+ {
+ caption: "with inlineSourceMap",
+ commandLineArgs: []string{"--build", "--verbose", "--inlineSourceMap"},
+ },
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--build", "--verbose", "--sourceMap"},
+ },
+ },
+ },
+ {
+ subScenario: "different options with incremental",
+ files: getBuildCommandLineDifferentOptionsMap("incremental"),
+ commandLineArgs: []string{"--build", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--build", "--verbose", "--sourceMap"},
+ },
+ {
+ caption: "should re-emit only js so they dont contain sourcemap",
+ },
+ {
+ caption: "with declaration, emit Dts and should not emit js",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration"},
+ },
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration", "--declarationMap"},
+ },
+ noChange,
+ {
+ caption: "local change",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10")
+ },
+ },
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration", "--declarationMap"},
+ },
+ noChange,
+ {
+ caption: "with inlineSourceMap",
+ commandLineArgs: []string{"--build", "--verbose", "--inlineSourceMap"},
+ },
+ {
+ caption: "with sourceMap",
+ commandLineArgs: []string{"--build", "--verbose", "--sourceMap"},
+ },
+ {
+ caption: "emit js files",
+ },
+ {
+ caption: "with declaration and declarationMap",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration", "--declarationMap"},
+ },
+ {
+ caption: "with declaration and declarationMap, should not re-emit",
+ commandLineArgs: []string{"--build", "--verbose", "--declaration", "--declarationMap"},
+ },
+ },
+ },
+ },
+ getBuildCommandLineEmitDeclarationOnlyTestCases([]string{"composite"}, ""),
+ getBuildCommandLineEmitDeclarationOnlyTestCases([]string{"incremental", "declaration"}, " with declaration and incremental"),
+ getBuildCommandLineEmitDeclarationOnlyTestCases([]string{"declaration"}, " with declaration"),
+ )
+
+ for _, test := range testCases {
+ test.run(t, "commandLine")
+ }
+}
+
+func TestBuildClean(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "file name and output name clashing",
+ files: FileMap{
+ "/home/src/workspaces/solution/index.js": "",
+ "/home/src/workspaces/solution/bar.ts": "",
+ "/home/src/workspaces/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "allowJs": true }
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "--clean"},
+ },
+ {
+ subScenario: "tsx with dts emit",
+ files: FileMap{
+ "/home/src/workspaces/solution/project/src/main.tsx": "export const x = 10;",
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "declaration": true },
+ "include": ["src/**/*.tsx", "src/**/*.ts"]
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "project", "-v", "--explainFiles"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "clean build",
+ commandLineArgs: []string{"-b", "project", "--clean"},
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "clean")
+ }
+}
+
+func TestBuildConfigFileErrors(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "when tsconfig extends the missing file",
+ files: FileMap{
+ "/home/src/workspaces/project/tsconfig.first.json": stringtestutil.Dedent(`
+ {
+ "extends": "./foobar.json",
+ "compilerOptions": {
+ "composite": true
+ }
+ }`),
+ "/home/src/workspaces/project/tsconfig.second.json": stringtestutil.Dedent(`
+ {
+ "extends": "./foobar.json",
+ "compilerOptions": {
+ "composite": true
+ }
+ }`),
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "./tsconfig.first.json" },
+ { "path": "./tsconfig.second.json" }
+ ]
+ }`),
+ },
+ commandLineArgs: []string{"--b"},
+ },
+ {
+ subScenario: "reports syntax errors in config file",
+ files: FileMap{
+ "/home/src/workspaces/project/a.ts": "export function foo() { }",
+ "/home/src/workspaces/project/b.ts": "export function bar() { }",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ },
+ "files": [
+ "a.ts"
+ "b.ts"
+ ]
+ }`),
+ },
+ commandLineArgs: []string{"--b"},
+ edits: []*tscEdit{
+ {
+ caption: "reports syntax errors after change to config file",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", ",", `, "declaration": true`)
+ },
+ },
+ {
+ caption: "reports syntax errors after change to ts file",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/project/a.ts", "export function fooBar() { }")
+ },
+ },
+ noChange,
+ {
+ caption: "builds after fixing config file errors",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/home/src/workspaces/project/tsconfig.json", stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true, "declaration": true
+ },
+ "files": [
+ "a.ts",
+ "b.ts"
+ ]
+ }`), false)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "missing config file",
+ files: FileMap{},
+ commandLineArgs: []string{"--b", "bogus.json"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "configFileErrors")
+ }
+}
+
+func TestBuildDemoProject(t *testing.T) {
+ t.Parallel()
+
+ getBuildDemoFileMap := func(modify func(FileMap)) FileMap {
+ files := FileMap{
+ "/user/username/projects/demo/animals/animal.ts": stringtestutil.Dedent(`
+ export type Size = "small" | "medium" | "large";
+ export default interface Animal {
+ size: Size;
+ }
+ `),
+ "/user/username/projects/demo/animals/dog.ts": stringtestutil.Dedent(`
+ import Animal from '.';
+ import { makeRandomName } from '../core/utilities';
+
+ export interface Dog extends Animal {
+ woof(): void;
+ name: string;
+ }
+
+ export function createDog(): Dog {
+ return ({
+ size: "medium",
+ woof: function(this: Dog) {
+ console.log(` + "`" + `${ this.name } says "Woof"!` + "`" + `);
+ },
+ name: makeRandomName()
+ });
+ }
+ `),
+ "/user/username/projects/demo/animals/index.ts": stringtestutil.Dedent(`
+ import Animal from './animal';
+
+ export default Animal;
+ import { createDog, Dog } from './dog';
+ export { createDog, Dog };
+ `),
+ "/user/username/projects/demo/animals/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../lib/animals",
+ "rootDir": "."
+ },
+ "references": [
+ { "path": "../core" }
+ ]
+ }
+ `),
+ "/user/username/projects/demo/core/utilities.ts": stringtestutil.Dedent(`
+
+ export function makeRandomName() {
+ return "Bob!?! ";
+ }
+
+ export function lastElementOf(arr: T[]): T | undefined {
+ if (arr.length === 0) return undefined;
+ return arr[arr.length - 1];
+ }
+ `),
+ "/user/username/projects/demo/core/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../lib/core",
+ "rootDir": "."
+ },
+ }
+ `),
+ "/user/username/projects/demo/zoo/zoo.ts": stringtestutil.Dedent(`
+ import { Dog, createDog } from '../animals/index';
+
+ export function createZoo(): Array {
+ return [
+ createDog()
+ ];
+ }
+ `),
+ "/user/username/projects/demo/zoo/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../lib/zoo",
+ "rootDir": "."
+ },
+ "references": [
+ {
+ "path": "../animals"
+ }
+ ]
+ }
+ `),
+ "/user/username/projects/demo/tsconfig-base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "declaration": true,
+ "target": "es5",
+ "module": "commonjs",
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "composite": true,
+ },
+ }
+ `),
+ "/user/username/projects/demo/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "files": [],
+ "references": [
+ {
+ "path": "./core"
+ },
+ {
+ "path": "./animals",
+ },
+ {
+ "path": "./zoo",
+ },
+ ],
+ }
+ `),
+ }
+ if modify != nil {
+ modify(files)
+ }
+ return files
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "in master branch with everything setup correctly and reports no error",
+ files: getBuildDemoFileMap(nil),
+ cwd: "/user/username/projects/demo",
+ commandLineArgs: []string{"--b", "--verbose"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "in circular branch reports the error about it by stopping build",
+ files: getBuildDemoFileMap(func(files FileMap) {
+ files["/user/username/projects/demo/core/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../lib/core",
+ "rootDir": "."
+ },
+ "references": [
+ {
+ "path": "../zoo",
+ }
+ ]
+ }
+ `)
+ }),
+ cwd: "/user/username/projects/demo",
+ commandLineArgs: []string{"--b", "--verbose"},
+ },
+ {
+ // !!! sheetal - this has missing errors from strada about files not in rootDir (3) and value is declared but not used (1)
+ subScenario: "in bad-ref branch reports the error about files not in rootDir at the import location",
+ files: getBuildDemoFileMap(func(files FileMap) {
+ files["/user/username/projects/demo/core/utilities.ts"] = `import * as A from '../animals'
+` + files["/user/username/projects/demo/core/utilities.ts"].(string)
+ }),
+ cwd: "/user/username/projects/demo",
+ commandLineArgs: []string{"--b", "--verbose"},
+ },
+ {
+ subScenario: "in circular is set in the reference",
+ files: getBuildDemoFileMap(func(files FileMap) {
+ files["/user/username/projects/demo/a/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../lib/a",
+ "rootDir": "."
+ },
+ "references": [
+ {
+ "path": "../b",
+ "circular": true
+ }
+ ]
+ }`)
+ files["/user/username/projects/demo/b/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "outDir": "../lib/b",
+ "rootDir": "."
+ },
+ "references": [
+ {
+ "path": "../a",
+ }
+ ]
+ }`)
+ files["/user/username/projects/demo/a/index.ts"] = "export const a = 10;"
+ files["/user/username/projects/demo/b/index.ts"] = "export const b = 10;"
+ files["/user/username/projects/demo/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "files": [],
+ "references": [
+ {
+ "path": "./core"
+ },
+ {
+ "path": "./animals",
+ },
+ {
+ "path": "./zoo",
+ },
+ {
+ "path": "./a",
+ },
+ {
+ "path": "./b",
+ },
+ ],
+ }`)
+ }),
+ cwd: "/user/username/projects/demo",
+ commandLineArgs: []string{"--b", "--verbose"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "demo")
+ }
+}
+
+func TestBuildEmitDeclarationOnly(t *testing.T) {
+ t.Parallel()
+ getBuildEmitDeclarationOnlyImportFileMap := func(declarationMap bool, circularRef bool) FileMap {
+ files := FileMap{
+ "/home/src/workspaces/project/src/a.ts": stringtestutil.Dedent(`
+ import { B } from "./b";
+
+ export interface A {
+ b: B;
+ }
+ `),
+ "/home/src/workspaces/project/src/b.ts": stringtestutil.Dedent(`
+ import { C } from "./c";
+
+ export interface B {
+ b: C;
+ }
+ `),
+ "/home/src/workspaces/project/src/c.ts": stringtestutil.Dedent(`
+ import { A } from "./a";
+
+ export interface C {
+ a: A;
+ }
+ `),
+ "/home/src/workspaces/project/src/index.ts": stringtestutil.Dedent(`
+ export { A } from "./a";
+ export { B } from "./b";
+ export { C } from "./c";
+ `),
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "target": "es5",
+ "module": "commonjs",
+ "declaration": true,
+ "declarationMap": %t,
+ "sourceMap": true,
+ "outDir": "./lib",
+ "composite": true,
+ "strict": true,
+ "esModuleInterop": true,
+ "alwaysStrict": true,
+ "rootDir": "src",
+ "emitDeclarationOnly": true,
+ },
+ }`, declarationMap)),
+ }
+ if !circularRef {
+ delete(files, "/home/src/workspaces/project/src/index.ts")
+ files["/home/src/workspaces/project/src/a.ts"] = stringtestutil.Dedent(`
+ export class B { prop = "hello"; }
+
+ export interface A {
+ b: B;
+ }
+ `)
+ }
+ return files
+ }
+ getBuildEmitDeclarationOnlyTestCase := func(declarationMap bool) *tscInput {
+ return &tscInput{
+ subScenario: `only dts output in circular import project with emitDeclarationOnly` + core.IfElse(declarationMap, " and declarationMap", ""),
+ files: getBuildEmitDeclarationOnlyImportFileMap(declarationMap, true),
+ commandLineArgs: []string{"--b", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/src/a.ts", "b: B;", "b: B; foo: any;")
+ },
+ },
+ },
+ }
+ }
+ testCases := []*tscInput{
+ getBuildEmitDeclarationOnlyTestCase(false),
+ getBuildEmitDeclarationOnlyTestCase(true),
+ {
+ subScenario: `only dts output in non circular imports project with emitDeclarationOnly`,
+ files: getBuildEmitDeclarationOnlyImportFileMap(true, false),
+ commandLineArgs: []string{"--b", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-doesnt-change",
+ edit: func(sys *testSys) {
+ sys.replaceFileText(
+ "/home/src/workspaces/project/src/a.ts",
+ "export interface A {",
+ stringtestutil.Dedent(`
+ class C { }
+ export interface A {`),
+ )
+ },
+ },
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/src/a.ts", "b: B;", "b: B; foo: any;")
+ },
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "emitDeclarationOnly")
+ }
+}
+
+func TestBuildFileDelete(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "detects deleted file",
+ files: FileMap{
+ "/home/src/workspaces/solution/child/child.ts": stringtestutil.Dedent(`
+ import { child2 } from "../child/child2";
+ export function child() {
+ child2();
+ }
+ `),
+ "/home/src/workspaces/solution/child/child2.ts": stringtestutil.Dedent(`
+ export function child2() {
+ }
+ `),
+ "/home/src/workspaces/solution/child/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true }
+ }
+ `),
+ "/home/src/workspaces/solution/main/main.ts": stringtestutil.Dedent(`
+ import { child } from "../child/child";
+ export function main() {
+ child();
+ }
+ `),
+ "/home/src/workspaces/solution/main/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "references": [{ "path": "../child" }],
+ }
+ `),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "main/tsconfig.json", "-v", "--traceResolution", "--explainFiles"},
+ edits: []*tscEdit{
+ {
+ caption: "delete child2 file",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/solution/child/child2.ts")
+ sys.removeNoError("/home/src/workspaces/solution/child/child2.js")
+ sys.removeNoError("/home/src/workspaces/solution/child/child2.d.ts")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "deleted file without composite",
+ files: FileMap{
+ "/home/src/workspaces/solution/child/child.ts": stringtestutil.Dedent(`
+ import { child2 } from "../child/child2";
+ export function child() {
+ child2();
+ }
+ `),
+ "/home/src/workspaces/solution/child/child2.ts": stringtestutil.Dedent(`
+ export function child2() {
+ }
+ `),
+ "/home/src/workspaces/solution/child/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { }
+ }
+ `),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "child/tsconfig.json", "-v", "--traceResolution", "--explainFiles"},
+ edits: []*tscEdit{
+ {
+ caption: "delete child2 file",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/solution/child/child2.ts")
+ sys.removeNoError("/home/src/workspaces/solution/child/child2.js")
+ },
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "fileDelete")
+ }
+}
+
+func TestBuildInferredTypeFromTransitiveModule(t *testing.T) {
+ t.Parallel()
+ getBuildInferredTypeFromTransitiveModuleMap := func(isolatedModules bool, lazyExtraContents string) FileMap {
+ return FileMap{
+ "/home/src/workspaces/project/bar.ts": stringtestutil.Dedent(`
+ interface RawAction {
+ (...args: any[]): Promise | void;
+ }
+ interface ActionFactory {
+ (target: T): T;
+ }
+ declare function foo(): ActionFactory;
+ export default foo()(function foobar(param: string): void {
+ });
+ `),
+ "/home/src/workspaces/project/bundling.ts": stringtestutil.Dedent(`
+ export class LazyModule {
+ constructor(private importCallback: () => Promise) {}
+ }
+
+ export class LazyAction<
+ TAction extends (...args: any[]) => any,
+ TModule
+ > {
+ constructor(_lazyModule: LazyModule, _getter: (module: TModule) => TAction) {
+ }
+ }
+ `),
+ "/home/src/workspaces/project/global.d.ts": stringtestutil.Dedent(`
+ interface PromiseConstructor {
+ new (): Promise;
+ }
+ declare var Promise: PromiseConstructor;
+ interface Promise {
+ }
+ `),
+ "/home/src/workspaces/project/index.ts": stringtestutil.Dedent(`
+ import { LazyAction, LazyModule } from './bundling';
+ const lazyModule = new LazyModule(() =>
+ import('./lazyIndex')
+ );
+ export const lazyBar = new LazyAction(lazyModule, m => m.bar);
+ `),
+ "/home/src/workspaces/project/lazyIndex.ts": stringtestutil.Dedent(`
+ export { default as bar } from './bar';
+ `) + lazyExtraContents,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "declaration": true,
+ "outDir": "obj",
+ "incremental": true,
+ "isolatedModules": %t,
+ },
+ }`, isolatedModules)),
+ }
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "inferred type from transitive module",
+ files: getBuildInferredTypeFromTransitiveModuleMap(false, ""),
+ commandLineArgs: []string{"--b", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/bar.ts", "param: string", "")
+ },
+ },
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/bar.ts", "foobar()", "foobar(param: string)")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "inferred type from transitive module with isolatedModules",
+ files: getBuildInferredTypeFromTransitiveModuleMap(true, ""),
+ commandLineArgs: []string{"--b", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/bar.ts", "param: string", "")
+ },
+ },
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/bar.ts", "foobar()", "foobar(param: string)")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "reports errors in files affected by change in signature with isolatedModules",
+ files: getBuildInferredTypeFromTransitiveModuleMap(true, stringtestutil.Dedent(`
+ import { default as bar } from './bar';
+ bar("hello");
+ `)),
+ commandLineArgs: []string{"--b", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/bar.ts", "param: string", "")
+ },
+ },
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/bar.ts", "foobar()", "foobar(param: string)")
+ },
+ },
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/bar.ts", "param: string", "")
+ },
+ },
+ {
+ caption: "Fix Error",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/lazyIndex.ts", `bar("hello")`, "bar()")
+ },
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "inferredTypeFromTransitiveModule")
+ }
+}
+
+func TestBuildJavascriptProjectEmit(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ // !!! sheetal errors seem different
+ subScenario: "loads js-based projects and emits them correctly",
+ files: FileMap{
+ "/home/src/workspaces/solution/common/nominal.js": stringtestutil.Dedent(`
+ /**
+ * @template T, Name
+ * @typedef {T & {[Symbol.species]: Name}} Nominal
+ */
+ module.exports = {};
+ `),
+ "/home/src/workspaces/solution/common/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ },
+ "include": ["nominal.js"],
+ }
+ `),
+ "/home/src/workspaces/solution/sub-project/index.js": stringtestutil.Dedent(`
+ import { Nominal } from '../common/nominal';
+
+ /**
+ * @typedef {Nominal} MyNominal
+ */
+ `),
+ "/home/src/workspaces/solution/sub-project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "../common" },
+ ],
+ "include": ["./index.js"],
+ }`),
+ "/home/src/workspaces/solution/sub-project-2/index.js": stringtestutil.Dedent(`
+ import { MyNominal } from '../sub-project/index';
+
+ const variable = {
+ key: /** @type {MyNominal} */('value'),
+ };
+
+ /**
+ * @return {keyof typeof variable}
+ */
+ export function getVar() {
+ return 'key';
+ }
+ `),
+ "/home/src/workspaces/solution/sub-project-2/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "../sub-project" },
+ ],
+ "include": ["./index.js"],
+ }`),
+ "/home/src/workspaces/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "./sub-project" },
+ { "path": "./sub-project-2" },
+ ],
+ "include": [],
+ }`),
+ "/home/src/workspaces/solution/tsconfig.base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "skipLibCheck": true,
+ "rootDir": "./",
+ "outDir": "../lib",
+ "allowJs": true,
+ "checkJs": true,
+ "declaration": true,
+ },
+ }`),
+ tscLibPath + "/lib.d.ts": strings.Replace(tscDefaultLibContent, "interface SymbolConstructor {", "interface SymbolConstructor {\n readonly species: symbol;", 1),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b"},
+ },
+ {
+ subScenario: `loads js-based projects with non-moved json files and emits them correctly`,
+ files: FileMap{
+ "/home/src/workspaces/solution/common/obj.json": stringtestutil.Dedent(`
+ {
+ "val": 42,
+ }`),
+ "/home/src/workspaces/solution/common/index.ts": stringtestutil.Dedent(`
+ import x = require("./obj.json");
+ export = x;
+ `),
+ "/home/src/workspaces/solution/common/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": null,
+ "composite": true,
+ },
+ "include": ["index.ts", "obj.json"],
+ }`),
+ "/home/src/workspaces/solution/sub-project/index.js": stringtestutil.Dedent(`
+ import mod from '../common';
+
+ export const m = mod;
+ `),
+ "/home/src/workspaces/solution/sub-project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "../common" },
+ ],
+ "include": ["./index.js"],
+ }`),
+ "/home/src/workspaces/solution/sub-project-2/index.js": stringtestutil.Dedent(`
+ import { m } from '../sub-project/index';
+
+ const variable = {
+ key: m,
+ };
+
+ export function getVar() {
+ return variable;
+ }
+ `),
+ "/home/src/workspaces/solution/sub-project-2/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "../sub-project" },
+ ],
+ "include": ["./index.js"],
+ }`),
+ "/home/src/workspaces/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "./sub-project" },
+ { "path": "./sub-project-2" },
+ ],
+ "include": [],
+ }`),
+ "/home/src/workspaces/solution/tsconfig.base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "skipLibCheck": true,
+ "rootDir": "./",
+ "outDir": "../out",
+ "allowJs": true,
+ "checkJs": true,
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "declaration": true,
+ },
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"-b"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "javascriptProjectEmit")
+ }
+}
+
+func TestBuildLateBoundSymbol(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "interface is merged and contains late bound member",
+ files: FileMap{
+ "/home/src/workspaces/project/src/globals.d.ts": stringtestutil.Dedent(`
+ interface SymbolConstructor {
+ (description?: string | number): symbol;
+ }
+ declare var Symbol: SymbolConstructor;
+ `),
+ "/home/src/workspaces/project/src/hkt.ts": `export interface HKT { }`,
+ "/home/src/workspaces/project/src/main.ts": stringtestutil.Dedent(`
+ import { HKT } from "./hkt";
+
+ const sym = Symbol();
+
+ declare module "./hkt" {
+ interface HKT {
+ [sym]: { a: T }
+ }
+ }
+ const x = 10;
+ type A = HKT[typeof sym];
+ `),
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "rootDir": "src",
+ "incremental": true,
+ },
+ }`),
+ },
+ commandLineArgs: []string{"--b", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-doesnt-change",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/project/src/main.ts", "const x = 10;", "")
+ },
+ },
+ {
+ caption: "incremental-declaration-doesnt-change",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/project/src/main.ts", "const x = 10;")
+ },
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "lateBoundSymbol")
+ }
+}
+
+func TestBuildModuleSpecifiers(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: `synthesized module specifiers resolve correctly`,
+ files: FileMap{
+ "/home/src/workspaces/packages/solution/common/nominal.ts": stringtestutil.Dedent(`
+ export declare type Nominal = T & {
+ [Symbol.species]: Name;
+ };
+ `),
+ "/home/src/workspaces/packages/solution/common/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true
+ },
+ "include": ["nominal.ts"]
+ }
+ `),
+ "/home/src/workspaces/packages/solution/sub-project/index.ts": stringtestutil.Dedent(`
+ import { Nominal } from '../common/nominal';
+
+ export type MyNominal = Nominal;
+ `),
+ "/home/src/workspaces/packages/solution/sub-project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "../common" }
+ ],
+ "include": ["./index.ts"]
+ }
+ `),
+ "/home/src/workspaces/packages/solution/sub-project-2/index.ts": stringtestutil.Dedent(`
+ import { MyNominal } from '../sub-project/index';
+
+ const variable = {
+ key: 'value' as MyNominal,
+ };
+
+ export function getVar(): keyof typeof variable {
+ return 'key';
+ }
+ `),
+ "/home/src/workspaces/packages/solution/sub-project-2/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "../sub-project" }
+ ],
+ "include": ["./index.ts"]
+ }
+ `),
+ "/home/src/workspaces/packages/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "./sub-project" },
+ { "path": "./sub-project-2" }
+ ],
+ "include": []
+ }
+ `),
+ "/home/src/workspaces/packages/tsconfig.base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "skipLibCheck": true,
+ "rootDir": "./",
+ "outDir": "lib"
+ }
+ }
+ `),
+ "/home/src/workspaces/packages/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "./solution" },
+ ],
+ "include": [],
+ }
+ `),
+ tscLibPath + "/lib.d.ts": strings.Replace(tscDefaultLibContent, "interface SymbolConstructor {", "interface SymbolConstructor {\n readonly species: symbol;", 1),
+ },
+ cwd: "/home/src/workspaces/packages",
+ commandLineArgs: []string{"-b", "--verbose"},
+ },
+ {
+ subScenario: `synthesized module specifiers across projects resolve correctly`,
+ files: FileMap{
+ "/home/src/workspaces/packages/src-types/index.ts": stringtestutil.Dedent(`
+ export * from './dogconfig.js';`),
+ "/home/src/workspaces/packages/src-types/dogconfig.ts": stringtestutil.Dedent(`
+ export interface DogConfig {
+ name: string;
+ }
+ `),
+ "/home/src/workspaces/packages/src-dogs/index.ts": stringtestutil.Dedent(`
+ export * from 'src-types';
+ export * from './lassie/lassiedog.js';
+ `),
+ "/home/src/workspaces/packages/src-dogs/dogconfig.ts": stringtestutil.Dedent(`
+ import { DogConfig } from 'src-types';
+
+ export const DOG_CONFIG: DogConfig = {
+ name: 'Default dog',
+ };
+ `),
+ "/home/src/workspaces/packages/src-dogs/dog.ts": stringtestutil.Dedent(`
+ import { DogConfig } from 'src-types';
+ import { DOG_CONFIG } from './dogconfig.js';
+
+ export abstract class Dog {
+
+ public static getCapabilities(): DogConfig {
+ return DOG_CONFIG;
+ }
+ }
+ `),
+ "/home/src/workspaces/packages/src-dogs/lassie/lassiedog.ts": stringtestutil.Dedent(`
+ import { Dog } from '../dog.js';
+ import { LASSIE_CONFIG } from './lassieconfig.js';
+
+ export class LassieDog extends Dog {
+ protected static getDogConfig = () => LASSIE_CONFIG;
+ }
+ `),
+ "/home/src/workspaces/packages/src-dogs/lassie/lassieconfig.ts": stringtestutil.Dedent(`
+ import { DogConfig } from 'src-types';
+
+ export const LASSIE_CONFIG: DogConfig = { name: 'Lassie' };
+ `),
+ "/home/src/workspaces/packages/tsconfig-base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "declaration": true,
+ "module": "node16",
+ },
+ }
+ `),
+ "/home/src/workspaces/packages/src-types/package.json": stringtestutil.Dedent(`
+ {
+ "type": "module",
+ "exports": "./index.js"
+ }`),
+ "/home/src/workspaces/packages/src-dogs/package.json": stringtestutil.Dedent(`
+ {
+ "type": "module",
+ "exports": "./index.js"
+ }`),
+ "/home/src/workspaces/packages/src-types/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "composite": true,
+ },
+ "include": [
+ "**/*",
+ ],
+ }`),
+ "/home/src/workspaces/packages/src-dogs/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig-base.json",
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "../src-types" },
+ ],
+ "include": [
+ "**/*",
+ ],
+ }`),
+ "/home/src/workspaces/packages/src-types/node_modules": vfstest.Symlink("/home/src/workspaces/packages"),
+ "/home/src/workspaces/packages/src-dogs/node_modules": vfstest.Symlink("/home/src/workspaces/packages"),
+ },
+ cwd: "/home/src/workspaces/packages",
+ commandLineArgs: []string{"-b", "src-types", "src-dogs", "--verbose"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "moduleSpecifiers")
+ }
+}
+
+func TestBuildOutputPaths(t *testing.T) {
+ t.Parallel()
+ type tscOutputPathScenario struct {
+ subScenario string
+ files FileMap
+ expectedDtsNames []string
+ }
+ runOutputPaths := func(s *tscOutputPathScenario) {
+ t.Helper()
+ input := &tscInput{
+ subScenario: s.subScenario,
+ files: s.files,
+ commandLineArgs: []string{"-b", "-v"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "Normal build without change, that does not block emit on error to show files that get emitted",
+ commandLineArgs: []string{"-p", "/home/src/workspaces/project/tsconfig.json"},
+ },
+ },
+ }
+ input.run(t, "outputPaths")
+ t.Run("GetOutputFileNames/"+s.subScenario, func(t *testing.T) {
+ t.Parallel()
+ sys := newTestSys(input, false)
+ config, _ := tsoptions.GetParsedCommandLineOfConfigFile("/home/src/workspaces/project/tsconfig.json", &core.CompilerOptions{}, sys, nil)
+ assert.DeepEqual(t, slices.Collect(config.GetOutputFileNames()), s.expectedDtsNames)
+ })
+ }
+ testCases := []*tscOutputPathScenario{
+ {
+ subScenario: "when rootDir is not specified",
+ files: FileMap{
+ "/home/src/workspaces/project/src/index.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "outDir": "dist",
+ },
+ }`),
+ },
+ expectedDtsNames: []string{
+ "/home/src/workspaces/project/dist/index.js",
+ },
+ },
+ {
+ subScenario: "when rootDir is not specified and is composite",
+ files: FileMap{
+ "/home/src/workspaces/project/src/index.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "outDir": "dist",
+ "composite": true,
+ },
+ }`),
+ },
+ expectedDtsNames: []string{
+ "/home/src/workspaces/project/dist/src/index.js",
+ "/home/src/workspaces/project/dist/src/index.d.ts",
+ },
+ },
+ {
+ subScenario: "when rootDir is specified",
+ files: FileMap{
+ "/home/src/workspaces/project/src/index.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src",
+ },
+ }`),
+ },
+ expectedDtsNames: []string{
+ "/home/src/workspaces/project/dist/index.js",
+ },
+ },
+ {
+ // !!! sheetal error missing as not yet implemented
+ subScenario: "when rootDir is specified but not all files belong to rootDir",
+ files: FileMap{
+ "/home/src/workspaces/project/src/index.ts": "export const x = 10;",
+ "/home/src/workspaces/project/types/type.ts": "export type t = string;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src",
+ },
+ }`),
+ },
+ expectedDtsNames: []string{
+ "/home/src/workspaces/project/dist/index.js",
+ "/home/src/workspaces/project/types/type.js",
+ },
+ },
+ {
+ // !!! sheetal error missing as not yet implemented
+ subScenario: "when rootDir is specified but not all files belong to rootDir and is composite",
+ files: FileMap{
+ "/home/src/workspaces/project/src/index.ts": "export const x = 10;",
+ "/home/src/workspaces/project/types/type.ts": "export type t = string;",
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src",
+ "composite": true
+ },
+ }`),
+ },
+ expectedDtsNames: []string{
+ "/home/src/workspaces/project/dist/index.js",
+ "/home/src/workspaces/project/dist/index.d.ts",
+ "/home/src/workspaces/project/types/type.js",
+ "/home/src/workspaces/project/types/type.d.ts",
+ },
+ },
+ }
+ for _, test := range testCases {
+ runOutputPaths(test)
+ }
+}
+
+func TestBuildProjectReferenceWithRootDirInParent(t *testing.T) {
+ t.Parallel()
+ getBuildProjectReferenceWithRootDirInParentFileMap := func(modify func(files FileMap)) FileMap {
+ files := FileMap{
+ "/home/src/workspaces/solution/src/main/a.ts": stringtestutil.Dedent(`
+ import { b } from './b';
+ const a = b;
+ `),
+ "/home/src/workspaces/solution/src/main/b.ts": stringtestutil.Dedent(`
+ export const b = 0;
+ `),
+ "/home/src/workspaces/solution/src/main/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ "references": [
+ { "path": "../other" },
+ ],
+ }`),
+ "/home/src/workspaces/solution/src/other/other.ts": stringtestutil.Dedent(`
+ export const Other = 0;
+ `),
+ "/home/src/workspaces/solution/src/other/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.base.json",
+ }
+ `),
+ "/home/src/workspaces/solution/tsconfig.base.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "rootDir": "./src/",
+ "outDir": "./dist/",
+ "skipDefaultLibCheck": true,
+ },
+ "exclude": [
+ "node_modules",
+ ],
+ }`),
+ }
+ if modify != nil {
+ modify(files)
+ }
+ return files
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "builds correctly",
+ files: getBuildProjectReferenceWithRootDirInParentFileMap(nil),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "src/main", "/home/src/workspaces/solution/src/other"},
+ },
+ {
+ subScenario: "reports error for same tsbuildinfo file because no rootDir in the base",
+ files: getBuildProjectReferenceWithRootDirInParentFileMap(
+ func(files FileMap) {
+ text, _ := files["/home/src/workspaces/solution/tsconfig.base.json"]
+ files["/home/src/workspaces/solution/tsconfig.base.json"] = strings.Replace(text.(string), `"rootDir": "./src/",`, "", 1)
+ },
+ ),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "src/main", "--verbose"},
+ },
+ {
+ subScenario: "reports error for same tsbuildinfo file",
+ files: getBuildProjectReferenceWithRootDirInParentFileMap(
+ func(files FileMap) {
+ files["/home/src/workspaces/solution/src/main/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true, "outDir": "../../dist/" },
+ "references": [{ "path": "../other" }]
+ }`)
+ files["/home/src/workspaces/solution/src/other/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true, "outDir": "../../dist/" },
+ }`)
+ },
+ ),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "src/main", "--verbose"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "reports error for same tsbuildinfo file without incremental",
+ files: getBuildProjectReferenceWithRootDirInParentFileMap(
+ func(files FileMap) {
+ files["/home/src/workspaces/solution/src/main/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "outDir": "../../dist/" },
+ "references": [{ "path": "../other" }]
+ }`)
+ files["/home/src/workspaces/solution/src/other/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true, "outDir": "../../dist/" },
+ }`)
+ },
+ ),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "src/main", "--verbose"},
+ },
+ {
+ subScenario: "reports error for same tsbuildinfo file without incremental with tsc",
+ files: getBuildProjectReferenceWithRootDirInParentFileMap(
+ func(files FileMap) {
+ files["/home/src/workspaces/solution/src/main/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "outDir": "../../dist/" },
+ "references": [{ "path": "../other" }]
+ }`)
+ files["/home/src/workspaces/solution/src/other/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true, "outDir": "../../dist/" },
+ }`)
+ },
+ ),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "src/other", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "Running tsc on main",
+ commandLineArgs: []string{"-p", "src/main"},
+ },
+ },
+ },
+ {
+ subScenario: "reports no error when tsbuildinfo differ",
+ files: getBuildProjectReferenceWithRootDirInParentFileMap(
+ func(files FileMap) {
+ delete(files, "/home/src/workspaces/solution/src/main/tsconfig.json")
+ delete(files, "/home/src/workspaces/solution/src/other/tsconfig.json")
+ files["/home/src/workspaces/solution/src/main/tsconfig.main.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true, "outDir": "../../dist/" },
+ "references": [{ "path": "../other/tsconfig.other.json" }]
+ }`)
+ files["/home/src/workspaces/solution/src/other/tsconfig.other.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true, "outDir": "../../dist/" },
+ }`)
+ },
+ ),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "src/main/tsconfig.main.json", "--verbose"},
+ edits: noChangeOnlyEdit,
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "projectReferenceWithRootDirInParent")
+ }
+}
+
+func TestBuildResolveJsonModule(t *testing.T) {
+ t.Parallel()
+ type buildResolveJsonModuleScenario struct {
+ subScenario string
+ tsconfigFiles string
+ additionalCompilerOptions string
+ skipOutdir bool
+ modifyFiles func(files FileMap)
+ edits []*tscEdit
+ }
+ getBuildResolveJsonModuleFileMap := func(composite bool, s *buildResolveJsonModuleScenario) FileMap {
+ var outDirStr string
+ if !s.skipOutdir {
+ outDirStr = `"outDir": "dist",`
+ }
+ files := FileMap{
+ "/home/src/workspaces/solution/project/src/hello.json": stringtestutil.Dedent(`
+ {
+ "hello": "world"
+ }`),
+ "/home/src/workspaces/solution/project/src/index.ts": stringtestutil.Dedent(`
+ import hello from "./hello.json"
+ export default hello.hello
+ `),
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "compilerOptions": {
+ "composite": %t,
+ "moduleResolution": "node",
+ "module": "commonjs",
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ %s
+ "skipDefaultLibCheck": true,
+ %s
+ },
+ %s
+ }`, composite, outDirStr, s.additionalCompilerOptions, s.tsconfigFiles)),
+ }
+ if s.modifyFiles != nil {
+ s.modifyFiles(files)
+ }
+ return files
+ }
+ getBuildResolveJsonModuleTestCases := func(scenarios []*buildResolveJsonModuleScenario) []*tscInput {
+ testCases := make([]*tscInput, 0, len(scenarios)*2)
+ for _, s := range scenarios {
+ testCases = append(
+ testCases,
+ &tscInput{
+ subScenario: s.subScenario,
+ files: getBuildResolveJsonModuleFileMap(true, s),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "project", "--v", "--explainFiles", "--listEmittedFiles"},
+ edits: s.edits,
+ },
+ &tscInput{
+ subScenario: s.subScenario + " non-composite",
+ files: getBuildResolveJsonModuleFileMap(false, s),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "project", "--v", "--explainFiles", "--listEmittedFiles"},
+ edits: s.edits,
+ },
+ )
+ }
+ return testCases
+ }
+ scenarios := []*buildResolveJsonModuleScenario{
+ {
+ subScenario: "include only",
+ tsconfigFiles: `"include": [ "src/**/*" ],`,
+ },
+ {
+ subScenario: "include only without outDir",
+ tsconfigFiles: `"include": [ "src/**/*" ],`,
+ skipOutdir: true,
+ },
+ {
+ subScenario: "include only with json not in rootDir",
+ tsconfigFiles: `"include": [ "src/**/*" ],`,
+ additionalCompilerOptions: `"rootDir": "src",`,
+ modifyFiles: func(files FileMap) {
+ text, _ := files["/home/src/workspaces/solution/project/src/hello.json"]
+ delete(files, "/home/src/workspaces/solution/project/src/hello.json")
+ files["/home/src/workspaces/solution/project/hello.json"] = text
+ text, _ = files["/home/src/workspaces/solution/project/src/index.ts"]
+ files["/home/src/workspaces/solution/project/src/index.ts"] = strings.Replace(text.(string), "./hello.json", "../hello.json", 1)
+ },
+ },
+ {
+ subScenario: "include only with json without rootDir but outside configDirectory",
+ tsconfigFiles: `"include": [ "src/**/*" ],`,
+ modifyFiles: func(files FileMap) {
+ text, _ := files["/home/src/workspaces/solution/project/src/hello.json"]
+ delete(files, "/home/src/workspaces/solution/project/src/hello.json")
+ files["/home/src/workspaces/solution/hello.json"] = text
+ text, _ = files["/home/src/workspaces/solution/project/src/index.ts"]
+ files["/home/src/workspaces/solution/project/src/index.ts"] = strings.Replace(text.(string), "./hello.json", "../../hello.json", 1)
+ },
+ },
+ {
+ subScenario: "include of json along with other include",
+ tsconfigFiles: `"include": [ "src/**/*", "src/**/*.json" ],`,
+ },
+ {
+ subScenario: "include of json along with other include and file name matches ts file",
+ tsconfigFiles: `"include": [ "src/**/*", "src/**/*.json" ],`,
+ modifyFiles: func(files FileMap) {
+ text, _ := files["/home/src/workspaces/solution/project/src/hello.json"]
+ delete(files, "/home/src/workspaces/solution/project/src/hello.json")
+ files["/home/src/workspaces/solution/project/src/index.json"] = text
+ text, _ = files["/home/src/workspaces/solution/project/src/index.ts"]
+ files["/home/src/workspaces/solution/project/src/index.ts"] = strings.Replace(text.(string), "./hello.json", "./index.json", 1)
+ },
+ },
+ {
+ subScenario: "files containing json file",
+ tsconfigFiles: `"files": [ "src/index.ts", "src/hello.json", ],`,
+ },
+ {
+ subScenario: "include and files",
+ tsconfigFiles: `"files": [ "src/hello.json" ], "include": [ "src/**/*" ],`,
+ },
+ {
+ subScenario: "sourcemap",
+ tsconfigFiles: `"files": [ "src/index.ts", "src/hello.json", ],`,
+ additionalCompilerOptions: `"sourceMap": true,`,
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "without outDir",
+ tsconfigFiles: `"files": [ "src/index.ts", "src/hello.json", ],`,
+ skipOutdir: true,
+ edits: noChangeOnlyEdit,
+ },
+ }
+ testCases := slices.Concat(
+ getBuildResolveJsonModuleTestCases(scenarios),
+ []*tscInput{
+ {
+ subScenario: "importing json module from project reference",
+ files: FileMap{
+ "/home/src/workspaces/solution/project/strings/foo.json": stringtestutil.Dedent(`
+ {
+ "foo": "bar baz"
+ }
+ `),
+ "/home/src/workspaces/solution/project/strings/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.json",
+ "include": ["foo.json"],
+ "references": [],
+ }
+ `),
+ "/home/src/workspaces/solution/project/main/index.ts": stringtestutil.Dedent(`
+ import { foo } from '../strings/foo.json';
+ console.log(foo);
+ `),
+ "/home/src/workspaces/solution/project/main/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../tsconfig.json",
+ "include": [
+ "./**/*.ts",
+ ],
+ "references": [{
+ "path": "../strings/tsconfig.json",
+ }],
+ }
+ `),
+ "/home/src/workspaces/solution/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "rootDir": "./",
+ "composite": true,
+ "resolveJsonModule": true,
+ "strict": true,
+ "esModuleInterop": true,
+ },
+ "references": [
+ { "path": "./strings/tsconfig.json" },
+ { "path": "./main/tsconfig.json" },
+ ],
+ "files": [],
+ }
+ `),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "project", "--verbose", "--explainFiles"},
+ edits: noChangeOnlyEdit,
+ },
+ },
+ )
+
+ for _, test := range testCases {
+ test.run(t, "resolveJsonModule")
+ }
+}
+
+func TestBuildRoots(t *testing.T) {
+ t.Parallel()
+ getBuildRootsFromProjectReferencedProjectFileMap := func(serverFirst bool) FileMap {
+ include := core.IfElse(serverFirst, `"src/**/*.ts", "../shared/src/**/*.ts"`, `"../shared/src/**/*.ts", "src/**/*.ts"`)
+ return FileMap{
+ "/home/src/workspaces/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ },
+ "references": [
+ { "path": "projects/server" },
+ { "path": "projects/shared" },
+ ],
+ }`),
+ "/home/src/workspaces/solution/projects/shared/src/myClass.ts": `export class MyClass { }`,
+ "/home/src/workspaces/solution/projects/shared/src/logging.ts": stringtestutil.Dedent(`
+ export function log(str: string) {
+ console.log(str);
+ }
+ `),
+ "/home/src/workspaces/solution/projects/shared/src/random.ts": stringtestutil.Dedent(`
+ export function randomFn(str: string) {
+ console.log(str);
+ }
+ `),
+ "/home/src/workspaces/solution/projects/shared/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ },
+ "include": ["src/**/*.ts"],
+ }`),
+ "/home/src/workspaces/solution/projects/server/src/server.ts": stringtestutil.Dedent(`
+ import { MyClass } from ':shared/myClass.js';
+ console.log('Hello, world!');
+ `),
+ "/home/src/workspaces/solution/projects/server/tsconfig.json": stringtestutil.Dedent(fmt.Sprintf(`
+ {
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "..",
+ "outDir": "./dist",
+ "paths": {
+ ":shared/*": ["./src/../../shared/src/*"],
+ },
+ },
+ "include": [ %s ],
+ "references": [
+ { "path": "../shared" },
+ ],
+ }`, include)),
+ }
+ }
+ getBuildRootsFromProjectReferencedProjectTestEdits := func() []*tscEdit {
+ return []*tscEdit{
+ noChange,
+ {
+ caption: "edit logging file",
+ edit: func(sys *testSys) {
+ sys.appendFile("/home/src/workspaces/solution/projects/shared/src/logging.ts", "export const x = 10;")
+ },
+ },
+ noChange,
+ {
+ caption: "delete random file",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/solution/projects/shared/src/random.ts")
+ },
+ },
+ noChange,
+ }
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: `when two root files are consecutive`,
+ files: FileMap{
+ "/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
+ "/home/src/workspaces/project/file2.ts": `export const y = "world";`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "include": ["*.ts"],
+ }`),
+ },
+ commandLineArgs: []string{"--b", "-v"},
+ edits: []*tscEdit{
+ {
+ caption: "delete file1",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/project/file1.ts")
+ sys.removeNoError("/home/src/workspaces/project/file1.js")
+ sys.removeNoError("/home/src/workspaces/project/file1.d.ts")
+ },
+ },
+ },
+ },
+ {
+ subScenario: `when multiple root files are consecutive`,
+ files: FileMap{
+ "/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
+ "/home/src/workspaces/project/file2.ts": `export const y = "world";`,
+ "/home/src/workspaces/project/file3.ts": `export const y = "world";`,
+ "/home/src/workspaces/project/file4.ts": `export const y = "world";`,
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "include": ["*.ts"],
+ }`),
+ },
+ commandLineArgs: []string{"--b", "-v"},
+ edits: []*tscEdit{
+ {
+ caption: "delete file1",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/project/file1.ts")
+ sys.removeNoError("/home/src/workspaces/project/file1.js")
+ sys.removeNoError("/home/src/workspaces/project/file1.d.ts")
+ },
+ },
+ },
+ },
+ {
+ subScenario: `when files are not consecutive`,
+ files: FileMap{
+ "/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
+ "/home/src/workspaces/project/random.d.ts": `export const random = "world";`,
+ "/home/src/workspaces/project/file2.ts": stringtestutil.Dedent(`
+ import { random } from "./random";
+ export const y = "world";
+ `),
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "include": ["file*.ts"],
+ }`),
+ },
+ commandLineArgs: []string{"--b", "-v"},
+ edits: []*tscEdit{
+ {
+ caption: "delete file1",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/project/file1.ts")
+ sys.removeNoError("/home/src/workspaces/project/file1.js")
+ sys.removeNoError("/home/src/workspaces/project/file1.d.ts")
+ },
+ },
+ },
+ },
+ {
+ subScenario: `when consecutive and non consecutive are mixed`,
+ files: FileMap{
+ "/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
+ "/home/src/workspaces/project/file2.ts": `export const y = "world";`,
+ "/home/src/workspaces/project/random.d.ts": `export const random = "hello";`,
+ "/home/src/workspaces/project/nonconsecutive.ts": stringtestutil.Dedent(`
+ import { random } from "./random";
+ export const nonConsecutive = "hello";
+ `),
+ "/home/src/workspaces/project/random1.d.ts": `export const random = "hello";`,
+ "/home/src/workspaces/project/asArray1.ts": stringtestutil.Dedent(`
+ import { random } from "./random1";
+ export const x = "hello";
+ `),
+ "/home/src/workspaces/project/asArray2.ts": `export const x = "hello";`,
+ "/home/src/workspaces/project/asArray3.ts": `export const x = "hello";`,
+ "/home/src/workspaces/project/random2.d.ts": `export const random = "hello";`,
+ "/home/src/workspaces/project/anotherNonConsecutive.ts": stringtestutil.Dedent(`
+ import { random } from "./random2";
+ export const nonConsecutive = "hello";
+ `),
+ "/home/src/workspaces/project/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "include": ["file*.ts", "nonconsecutive*.ts", "asArray*.ts", "anotherNonConsecutive.ts"],
+ }`),
+ },
+ commandLineArgs: []string{"--b", "-v"},
+ edits: []*tscEdit{
+ {
+ caption: "delete file1",
+ edit: func(sys *testSys) {
+ sys.removeNoError("/home/src/workspaces/project/file1.ts")
+ sys.removeNoError("/home/src/workspaces/project/file1.js")
+ sys.removeNoError("/home/src/workspaces/project/file1.d.ts")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when root file is from referenced project",
+ files: getBuildRootsFromProjectReferencedProjectFileMap(true),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "projects/server", "-v", "--traceResolution", "--explainFiles"},
+ edits: getBuildRootsFromProjectReferencedProjectTestEdits(),
+ },
+ {
+ subScenario: "when root file is from referenced project and shared is first",
+ files: getBuildRootsFromProjectReferencedProjectFileMap(false),
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "projects/server", "-v", "--traceResolution", "--explainFiles"},
+ edits: getBuildRootsFromProjectReferencedProjectTestEdits(),
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "roots")
+ }
+}
+
+func TestBuildSample(t *testing.T) {
+ t.Parallel()
+
+ getBuildSampleFileMap := func(modify func(files FileMap)) FileMap {
+ files := FileMap{
+ "/user/username/projects/sample1/core/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "declarationMap": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`),
+ "/user/username/projects/sample1/core/index.ts": stringtestutil.Dedent(`
+ export const someString: string = "HELLO WORLD";
+ export function leftPad(s: string, n: number) { return s + n; }
+ export function multiply(a: number, b: number) { return a * b; }
+ `),
+ "/user/username/projects/sample1/core/some_decl.d.ts": `declare const dts: any;`,
+ "/user/username/projects/sample1/core/anotherModule.ts": `export const World = "hello";`,
+ "/user/username/projects/sample1/logic/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "sourceMap": true,
+ "skipDefaultLibCheck": true,
+ },
+ "references": [
+ { "path": "../core" },
+ ],
+ }`),
+ "/user/username/projects/sample1/logic/index.ts": stringtestutil.Dedent(`
+ import * as c from '../core/index';
+ export function getSecondsInDay() {
+ return c.multiply(10, 15);
+ }
+ import * as mod from '../core/anotherModule';
+ export const m = mod;
+ `),
+ "/user/username/projects/sample1/tests/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../core" },
+ { "path": "../logic" },
+ ],
+ "files": ["index.ts"],
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`),
+ "/user/username/projects/sample1/tests/index.ts": stringtestutil.Dedent(`
+ import * as c from '../core/index';
+ import * as logic from '../logic/index';
+
+ c.leftPad("", 10);
+ logic.getSecondsInDay();
+
+ import * as mod from '../core/anotherModule';
+ export const m = mod;
+ `),
+ }
+ if modify != nil {
+ modify(files)
+ }
+ return files
+ }
+ getBuildSampleCoreChangeEdits := func() []*tscEdit {
+ return []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.appendFile(
+ "/user/username/projects/sample1/core/index.ts",
+ `
+export class someClass { }`,
+ )
+ },
+ },
+ {
+ caption: "incremental-declaration-doesnt-change",
+ edit: func(sys *testSys) {
+ sys.appendFile(
+ "/user/username/projects/sample1/core/index.ts",
+ `
+class someClass2 { }`,
+ )
+ },
+ },
+ noChange,
+ }
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "builds correctly when outDir is specified",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/logic/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "sourceMap": true,
+ "outDir": "outDir",
+ },
+ "references": [
+ { "path": "../core" },
+ ],
+ }`)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests"},
+ },
+ {
+ subScenario: "builds correctly when declarationDir is specified",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/logic/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "sourceMap": true,
+ "declarationDir": "out/decls",
+ },
+ "references": [
+ { "path": "../core" },
+ ],
+ }`)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests"},
+ },
+ {
+ subScenario: "builds correctly when project is not composite or doesnt have any references",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ text, _ := files["/user/username/projects/sample1/core/tsconfig.json"]
+ files["/user/username/projects/sample1/core/tsconfig.json"] = strings.Replace(text.(string), `"composite": true,`, "", 1)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "core", "--verbose"},
+ },
+ {
+ subScenario: "does not write any files in a dry build",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--dry"},
+ },
+ {
+ subScenario: "removes all files it built",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests"},
+ edits: []*tscEdit{
+ {
+ caption: "removes all files it built",
+ commandLineArgs: []string{"--b", "tests", "--clean"},
+ },
+ {
+ caption: "no change --clean",
+ commandLineArgs: []string{"--b", "tests", "--clean"},
+ },
+ },
+ },
+ {
+ subScenario: "cleaning project in not build order doesnt throw error",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "logic2", "--clean"},
+ },
+ {
+ subScenario: "always builds under with force option",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--force"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "can detect when and what to rebuild",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ // Update a file in the leaf node (tests), only it should rebuild the last one
+ caption: "Only builds the leaf node project",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/user/username/projects/sample1/tests/index.ts", "const m = 10;", false)
+ },
+ },
+ {
+ // Update a file in the parent (without affecting types), should get fast downstream builds
+ caption: "Detects type-only changes in upstream projects",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/index.ts", "HELLO WORLD", "WELCOME PLANET")
+ },
+ },
+ {
+ caption: "rebuilds when tsconfig changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es2020"`)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when input file text does not change but its modified time changes",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "upstream project changes without changing file text",
+ edit: func(sys *testSys) {
+ err := sys.FS().Chtimes("/user/username/projects/sample1/core/index.ts", time.Time{}, sys.Now())
+ if err != nil {
+ panic(err)
+ }
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when declarationMap changes",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "Disable declarationMap",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/tsconfig.json", `"declarationMap": true,`, `"declarationMap": false,`)
+ },
+ },
+ {
+ caption: "Enable declarationMap",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/tsconfig.json", `"declarationMap": false,`, `"declarationMap": true,`)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "indicates that it would skip builds during a dry build",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests"},
+ edits: []*tscEdit{
+ {
+ caption: "--dry",
+ commandLineArgs: []string{"--b", "tests", "--dry"},
+ },
+ },
+ },
+ {
+ subScenario: "rebuilds from start if force option is set",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests"},
+ edits: []*tscEdit{
+ {
+ caption: "--force build",
+ commandLineArgs: []string{"--b", "tests", "--verbose", "--force"},
+ },
+ },
+ },
+ {
+ subScenario: "tsbuildinfo has error",
+ files: FileMap{
+ "/home/src/workspaces/project/main.ts": "export const x = 10;",
+ "/home/src/workspaces/project/tsconfig.json": "{}",
+ "/home/src/workspaces/project/tsconfig.tsbuildinfo": "Some random string",
+ },
+ commandLineArgs: []string{"--b", "-i", "-v"},
+ edits: []*tscEdit{
+ {
+ caption: "tsbuildinfo written has error",
+ edit: func(sys *testSys) {
+ // This is to ensure the non incremental doesnt crash - as it wont have tsbuildInfo
+ if !sys.forIncrementalCorrectness {
+ sys.prependFile("/home/src/workspaces/project/tsconfig.tsbuildinfo", "Some random string")
+ sys.replaceFileText("/home/src/workspaces/project/tsconfig.tsbuildinfo", fmt.Sprintf(`"version":"%s"`, core.Version()), fmt.Sprintf(`"version":"%s"`, harnessutil.FakeTSVersion)) // build info won't parse, need to manually sterilize for baseline
+ }
+ },
+ },
+ },
+ },
+ {
+ subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "convert tsbuildInfo version to something that is say to previous version",
+ edit: func(sys *testSys) {
+ // This is to ensure the non incremental doesnt crash - as it wont have tsbuildInfo
+ if !sys.forIncrementalCorrectness {
+ sys.replaceFileText("/user/username/projects/sample1/core/tsconfig.tsbuildinfo", fmt.Sprintf(`"version":"%s"`, harnessutil.FakeTSVersion), fmt.Sprintf(`"version":"%s"`, "FakeTsPreviousVersion"))
+ sys.replaceFileText("/user/username/projects/sample1/logic/tsconfig.tsbuildinfo", fmt.Sprintf(`"version":"%s"`, harnessutil.FakeTSVersion), fmt.Sprintf(`"version":"%s"`, "FakeTsPreviousVersion"))
+ sys.replaceFileText("/user/username/projects/sample1/tests/tsconfig.tsbuildinfo", fmt.Sprintf(`"version":"%s"`, harnessutil.FakeTSVersion), fmt.Sprintf(`"version":"%s"`, "FakeTsPreviousVersion"))
+ }
+ },
+ },
+ },
+ },
+ {
+ subScenario: "rebuilds when extended config file changes",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/tests/tsconfig.base.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "target": "es5"
+ }
+ }`)
+ text, _ := files["/user/username/projects/sample1/tests/tsconfig.json"]
+ files["/user/username/projects/sample1/tests/tsconfig.json"] = strings.Replace(text.(string), `"references": [`, `"extends": "./tsconfig.base.json", "references": [`, 1)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "change extended file",
+ edit: func(sys *testSys) {
+ sys.writeFileNoError("/user/username/projects/sample1/tests/tsconfig.base.json", stringtestutil.Dedent(`
+ {
+ "compilerOptions": { }
+ }`), false)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "building project in not build order doesnt throw error",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "logic2/tsconfig.json", "--verbose"},
+ },
+ {
+ subScenario: "builds downstream projects even if upstream projects have errors",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ text, _ := files["/user/username/projects/sample1/logic/index.ts"]
+ files["/user/username/projects/sample1/logic/index.ts"] = strings.Replace(text.(string), "c.multiply(10, 15)", `c.muitply()`, 1)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "skips builds downstream projects if upstream projects have errors with stopBuildOnErrors",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ text, _ := files["/user/username/projects/sample1/core/index.ts"]
+ files["/user/username/projects/sample1/core/index.ts"] = text.(string) + `multiply();`
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose", "--stopBuildOnErrors"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "fix error",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/index.ts", "multiply();", "")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "skips builds downstream projects if upstream projects have errors with stopBuildOnErrors when test does not reference core",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/tests/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../logic" },
+ ],
+ "files": ["index.ts"],
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`)
+ text, _ := files["/user/username/projects/sample1/core/index.ts"]
+ files["/user/username/projects/sample1/core/index.ts"] = text.(string) + `multiply();`
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose", "--stopBuildOnErrors"},
+ edits: []*tscEdit{
+ noChange,
+ {
+ caption: "fix error",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/index.ts", "multiply();", "")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "listFiles",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--listFiles"},
+ edits: getBuildSampleCoreChangeEdits(),
+ },
+ {
+ subScenario: "listEmittedFiles",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--listEmittedFiles"},
+ edits: getBuildSampleCoreChangeEdits(),
+ },
+ {
+ subScenario: "explainFiles",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--explainFiles", "--v"},
+ edits: getBuildSampleCoreChangeEdits(),
+ },
+ {
+ subScenario: "sample",
+ files: getBuildSampleFileMap(nil),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: slices.Concat(
+ getBuildSampleCoreChangeEdits(),
+ []*tscEdit{
+ {
+ caption: "when logic config changes declaration dir",
+ edit: func(sys *testSys) {
+ sys.replaceFileText(
+ "/user/username/projects/sample1/logic/tsconfig.json",
+ `"declaration": true,`,
+ `"declaration": true,
+ "declarationDir": "decls",`,
+ )
+ },
+ },
+ noChange,
+ },
+ ),
+ },
+ {
+ subScenario: "when logic specifies tsBuildInfoFile",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ text, _ := files["/user/username/projects/sample1/logic/tsconfig.json"]
+ files["/user/username/projects/sample1/logic/tsconfig.json"] = strings.Replace(
+ text.(string),
+ `"composite": true,`,
+ `"composite": true,
+ "tsBuildInfoFile": "ownFile.tsbuildinfo",`,
+ 1,
+ )
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ },
+ {
+ subScenario: "when declaration option changes",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/core/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "core", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when target option changes",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files[getTestLibPathFor("esnext.full")] = `///
+/// `
+ files[tscLibPath+"/lib.d.ts"] = `///
+/// `
+ files["/user/username/projects/sample1/core/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "listFiles": true,
+ "listEmittedFiles": true,
+ "target": "esnext",
+ },
+ }`)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "core", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/tsconfig.json", `esnext`, `es5`)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when module option changes",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/core/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "incremental": true,
+ "module": "node18",
+ },
+ }`)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "core", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/core/tsconfig.json", `node18`, `nodenext`)
+ },
+ },
+ },
+ },
+ {
+ subScenario: "when esModuleInterop option changes",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/tests/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../core" },
+ { "path": "../logic" },
+ ],
+ "files": ["index.ts"],
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "skipDefaultLibCheck": true,
+ "esModuleInterop": false,
+ },
+ }`)
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ edits: []*tscEdit{
+ {
+ caption: "incremental-declaration-changes",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/user/username/projects/sample1/tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`)
+ },
+ },
+ },
+ },
+ {
+ // !!! sheetal this is not reporting error as file not found is not yet implemented
+ subScenario: "reports error if input file is missing",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/core/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "files": ["anotherModule.ts", "index.ts", "some_decl.d.ts"],
+ }`)
+ delete(files, "/user/username/projects/sample1/core/anotherModule.ts")
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose"},
+ },
+ {
+ // !!! sheetal this is not reporting error as file not found is not yet implemented
+ subScenario: "reports error if input file is missing with force",
+ files: getBuildSampleFileMap(func(files FileMap) {
+ files["/user/username/projects/sample1/core/tsconfig.json"] = stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "files": ["anotherModule.ts", "index.ts", "some_decl.d.ts"],
+ }`)
+ delete(files, "/user/username/projects/sample1/core/anotherModule.ts")
+ }),
+ cwd: "/user/username/projects/sample1",
+ commandLineArgs: []string{"--b", "tests", "--verbose", "--force"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "sample")
+ }
+}
+
+func TestBuildTransitiveReferences(t *testing.T) {
+ t.Parallel()
+
+ getBuildTransitiveReferencesFileMap := func(modify func(files FileMap)) FileMap {
+ files := FileMap{
+ "/user/username/projects/transitiveReferences/refs/a.d.ts": stringtestutil.Dedent(`
+ export class X {}
+ export class A {}
+ `),
+ "/user/username/projects/transitiveReferences/a.ts": stringtestutil.Dedent(`
+ export class A {}
+ `),
+ "/user/username/projects/transitiveReferences/b.ts": stringtestutil.Dedent(`
+ import {A} from '@ref/a';
+ export const b = new A();
+ `),
+ "/user/username/projects/transitiveReferences/c.ts": stringtestutil.Dedent(`
+ import {b} from './b';
+ import {X} from "@ref/a";
+ b;
+ X;
+ `),
+ "/user/username/projects/transitiveReferences/tsconfig.a.json": stringtestutil.Dedent(`
+ {
+ "files": ["a.ts"],
+ "compilerOptions": {
+ "composite": true,
+ },
+ }`),
+ "/user/username/projects/transitiveReferences/tsconfig.b.json": stringtestutil.Dedent(`
+ {
+ "files": ["b.ts"],
+ "compilerOptions": {
+ "composite": true,
+ "paths": {
+ "@ref/*": ["./*"],
+ },
+ },
+ "references": [{ "path": "tsconfig.a.json" }],
+ }`),
+ "/user/username/projects/transitiveReferences/tsconfig.c.json": stringtestutil.Dedent(`
+ {
+ "files": ["c.ts"],
+ "compilerOptions": {
+ "paths": {
+ "@ref/*": ["./refs/*"],
+ },
+ },
+ "references": [{ "path": "tsconfig.b.json" }],
+ }`),
+ }
+ if modify != nil {
+ modify(files)
+ }
+ return files
+ }
+ testCases := []*tscInput{
+ {
+ subScenario: "builds correctly",
+ files: getBuildTransitiveReferencesFileMap(nil),
+ cwd: "/user/username/projects/transitiveReferences",
+ commandLineArgs: []string{"--b", "tsconfig.c.json", "--listFiles"},
+ },
+ {
+ subScenario: "reports error about module not found with node resolution with external module name",
+ files: getBuildTransitiveReferencesFileMap(func(files FileMap) {
+ files["/user/username/projects/transitiveReferences/b.ts"] = `import {A} from 'a';
+export const b = new A();`
+ files["/user/username/projects/transitiveReferences/tsconfig.b.json"] = stringtestutil.Dedent(`
+ {
+ "files": ["b.ts"],
+ "compilerOptions": {
+ "composite": true,
+ "module": "nodenext",
+ },
+ "references": [{ "path": "tsconfig.a.json" }],
+ }`)
+ }),
+ cwd: "/user/username/projects/transitiveReferences",
+ commandLineArgs: []string{"--b", "tsconfig.c.json", "--listFiles"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "transitiveReferences")
+ }
+}
+
+func TestBuildSolutionProject(t *testing.T) {
+ t.Parallel()
+ testCases := []*tscInput{
+ {
+ subScenario: "verify that subsequent builds after initial build doesnt build anything",
+ files: FileMap{
+ "/home/src/workspaces/solution/src/folder/index.ts": `export const x = 10;`,
+ "/home/src/workspaces/solution/src/folder/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "files": ["index.ts"],
+ "compilerOptions": {
+ "composite": true
+ }
+ }
+ `),
+ "/home/src/workspaces/solution/src/folder2/index.ts": `export const x = 10;`,
+ "/home/src/workspaces/solution/src/folder2/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "files": ["index.ts"],
+ "compilerOptions": {
+ "composite": true
+ }
+ }
+ `),
+ "/home/src/workspaces/solution/src/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "files": [],
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "./folder" },
+ { "path": "./folder2" },
+ ]
+ }`),
+ "/home/src/workspaces/solution/tests/index.ts": `export const x = 10;`,
+ "/home/src/workspaces/solution/tests/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "files": ["index.ts"],
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "../src" }
+ ]
+ }
+ `),
+ "/home/src/workspaces/solution/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "files": [],
+ "compilerOptions": {
+ "composite": true
+ },
+ "references": [
+ { "path": "./src" },
+ { "path": "./tests" }
+ ]
+ }
+ `),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "--v"},
+ edits: noChangeOnlyEdit,
+ },
+ {
+ subScenario: "when solution is referenced indirectly",
+ files: FileMap{
+ "/home/src/workspaces/solution/project1/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "references": []
+ }
+ `),
+ "/home/src/workspaces/solution/project2/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "references": []
+ }
+ `),
+ "/home/src/workspaces/solution/project2/src/b.ts": "export const b = 10;",
+ "/home/src/workspaces/solution/project3/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "references": [
+ { "path": "../project1" },
+ { "path": "../project2" }
+ ]
+ }
+ `),
+ "/home/src/workspaces/solution/project3/src/c.ts": "export const c = 10;",
+ "/home/src/workspaces/solution/project4/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": { "composite": true },
+ "references": [{ "path": "../project3" }]
+ }
+ `),
+ "/home/src/workspaces/solution/project4/src/d.ts": "export const d = 10;",
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "project4", "--verbose", "--explainFiles"},
+ edits: []*tscEdit{
+ {
+ caption: "modify project3 file",
+ edit: func(sys *testSys) {
+ sys.replaceFileText("/home/src/workspaces/solution/project3/src/c.ts", "c = ", "cc = ")
+ },
+ },
+ },
+ },
+ {
+ subScenario: "has empty files diagnostic when files is empty and no references are provided",
+ files: FileMap{
+ "/home/src/workspaces/solution/no-references/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [],
+ "files": [],
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "no-references"},
+ },
+ {
+ subScenario: "does not have empty files diagnostic when files is empty and references are provided",
+ files: FileMap{
+ "/home/src/workspaces/solution/core/index.ts": "export function multiply(a: number, b: number) { return a * b; }",
+ "/home/src/workspaces/solution/core/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "declarationMap": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`),
+ "/home/src/workspaces/solution/with-references/tsconfig.json": stringtestutil.Dedent(`
+ {
+ "references": [
+ { "path": "../core" },
+ ],
+ "files": [],
+ "compilerOptions": {
+ "composite": true,
+ "declaration": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipDefaultLibCheck": true,
+ },
+ }`),
+ },
+ cwd: "/home/src/workspaces/solution",
+ commandLineArgs: []string{"--b", "with-references"},
+ },
+ }
+
+ for _, test := range testCases {
+ test.run(t, "solution")
+ }
+}
diff --git a/internal/execute/tscwatch_test.go b/internal/execute/tsctests/tscwatch_test.go
similarity index 99%
rename from internal/execute/tscwatch_test.go
rename to internal/execute/tsctests/tscwatch_test.go
index eabb675791..58517bdb35 100644
--- a/internal/execute/tscwatch_test.go
+++ b/internal/execute/tsctests/tscwatch_test.go
@@ -1,4 +1,4 @@
-package execute_test
+package tsctests
import (
"strings"
diff --git a/internal/execute/watcher.go b/internal/execute/watcher.go
index 738c24ae17..aec6179600 100644
--- a/internal/execute/watcher.go
+++ b/internal/execute/watcher.go
@@ -9,17 +9,19 @@ import (
"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/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/incremental"
+ "github.com/microsoft/typescript-go/internal/execute/tsc"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
)
type Watcher struct {
- sys System
- configFileName string
- options *tsoptions.ParsedCommandLine
- reportDiagnostic diagnosticReporter
- testing CommandLineTesting
+ sys tsc.System
+ configFileName string
+ options *tsoptions.ParsedCommandLine
+ reportDiagnostic tsc.DiagnosticReporter
+ reportErrorSummary tsc.DiagnosticsReporter
+ testing tsc.CommandLineTesting
host compiler.CompilerHost
program *incremental.Program
@@ -27,12 +29,15 @@ type Watcher struct {
configModified bool
}
-func createWatcher(sys System, configParseResult *tsoptions.ParsedCommandLine, reportDiagnostic diagnosticReporter, testing CommandLineTesting) *Watcher {
+var _ tsc.Watcher = (*Watcher)(nil)
+
+func createWatcher(sys tsc.System, configParseResult *tsoptions.ParsedCommandLine, reportDiagnostic tsc.DiagnosticReporter, reportErrorSummary tsc.DiagnosticsReporter, testing tsc.CommandLineTesting) *Watcher {
w := &Watcher{
- sys: sys,
- options: configParseResult,
- reportDiagnostic: reportDiagnostic,
- testing: testing,
+ sys: sys,
+ options: configParseResult,
+ reportDiagnostic: reportDiagnostic,
+ reportErrorSummary: reportErrorSummary,
+ testing: testing,
// reportWatchStatus: createWatchStatusReporter(sys, configParseResult.CompilerOptions().Pretty),
}
if configParseResult.ConfigFile != nil {
@@ -72,13 +77,13 @@ func (w *Watcher) DoCycle() {
Config: w.options,
Host: w.host,
JSDocParsingMode: ast.JSDocParsingModeParseForTypeErrors,
- }), w.program, w.testing != nil)
+ }), w.program, nil, w.testing != nil)
if w.hasBeenModified(w.program.GetProgram()) {
- fmt.Fprintln(w.sys.Writer(), "build starting at ", w.sys.Now())
+ fmt.Fprintln(w.sys.Writer(), "build starting at", w.sys.Now().Format("03:04:05 PM"))
timeStart := w.sys.Now()
w.compileAndEmit()
- fmt.Fprintln(w.sys.Writer(), "build finished in ", w.sys.Now().Sub(timeStart))
+ fmt.Fprintf(w.sys.Writer(), "build finished in %.3fs\n", w.sys.Now().Sub(timeStart).Seconds())
} else {
// print something???
// fmt.Fprintln(w.sys.Writer(), "no changes detected at ", w.sys.Now())
@@ -88,7 +93,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.program.GetProgram(), w.reportDiagnostic, w.testing)
+ tsc.EmitFilesAndReportErrors(w.sys, w.program, w.program.GetProgram(), w.reportDiagnostic, w.reportErrorSummary, w.sys.Writer(), tsc.CompileTimes{}, w.testing)
}
func (w *Watcher) hasErrorsInTsConfig() bool {
diff --git a/internal/module/resolver.go b/internal/module/resolver.go
index 815c3ad62b..780f0deb67 100644
--- a/internal/module/resolver.go
+++ b/internal/module/resolver.go
@@ -4,6 +4,7 @@ import (
"fmt"
"slices"
"strings"
+ "sync"
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/collections"
@@ -77,6 +78,12 @@ type resolutionState struct {
failedLookupLocations []string
affectingLocations []string
diagnostics []*ast.Diagnostic
+
+ // Similar to whats on resolver but only done if compilerOptions are for project reference redirect
+ // Cached representation for `core.CompilerOptions.paths`.
+ // Doesn't handle other path patterns like in `typesVersions`.
+ parsedPatternsForPathsOnce sync.Once
+ parsedPatternsForPaths *ParsedPatterns
}
func newResolutionState(
@@ -1117,6 +1124,16 @@ func (r *resolutionState) tryLoadModuleUsingOptionalResolutionSettings() *resolv
}
}
+func (r *resolutionState) getParsedPatternsForPaths() *ParsedPatterns {
+ if r.compilerOptions == r.resolver.compilerOptions {
+ return r.resolver.getParsedPatternsForPaths()
+ }
+ r.parsedPatternsForPathsOnce.Do(func() {
+ r.parsedPatternsForPaths = TryParsePatterns(r.compilerOptions.Paths)
+ })
+ return r.parsedPatternsForPaths
+}
+
func (r *resolutionState) tryLoadModuleUsingPathsIfEligible() *resolved {
if r.compilerOptions.Paths.Size() > 0 && !tspath.PathIsRelative(r.name) {
if r.tracer != nil {
@@ -1126,7 +1143,7 @@ func (r *resolutionState) tryLoadModuleUsingPathsIfEligible() *resolved {
return continueSearching()
}
baseDirectory := r.compilerOptions.GetPathsBasePath(r.resolver.host.GetCurrentDirectory())
- pathPatterns := r.resolver.getParsedPatternsForPaths()
+ pathPatterns := r.getParsedPatternsForPaths()
return r.tryLoadModuleUsingPaths(
r.extensions,
r.name,
diff --git a/internal/modulespecifiers/specifiers.go b/internal/modulespecifiers/specifiers.go
index 588f5a8b5c..8cdcfc6b7d 100644
--- a/internal/modulespecifiers/specifiers.go
+++ b/internal/modulespecifiers/specifiers.go
@@ -203,7 +203,7 @@ func getEachFileNameOfModule(
cwd := host.GetCurrentDirectory()
importedPath := tspath.ToPath(importedFileName, cwd, host.UseCaseSensitiveFileNames())
var referenceRedirect string
- outputAndReference := host.GetOutputAndProjectReference(importedPath)
+ outputAndReference := host.GetProjectReferenceFromSource(importedPath)
if outputAndReference != nil && outputAndReference.OutputDts != "" {
referenceRedirect = outputAndReference.OutputDts
}
diff --git a/internal/modulespecifiers/types.go b/internal/modulespecifiers/types.go
index 309fc8ab6c..eb9881f656 100644
--- a/internal/modulespecifiers/types.go
+++ b/internal/modulespecifiers/types.go
@@ -52,7 +52,7 @@ type ModuleSpecifierGenerationHost interface {
UseCaseSensitiveFileNames() bool
GetCurrentDirectory() string
- GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference
+ GetProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference
GetRedirectTargets(path tspath.Path) []string
GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFileName) string
diff --git a/internal/outputpaths/outputpaths.go b/internal/outputpaths/outputpaths.go
index a075cd481d..097a7ccc2c 100644
--- a/internal/outputpaths/outputpaths.go
+++ b/internal/outputpaths/outputpaths.go
@@ -53,7 +53,7 @@ func GetOutputPathsFor(sourceFile *ast.SourceFile, options *core.CompilerOptions
if options.EmitDeclarationOnly != core.TSTrue && !isJsonEmittedToSameLocation {
paths.jsFilePath = ownOutputFilePath
if !ast.IsJsonSourceFile(sourceFile) {
- paths.sourceMapFilePath = getSourceMapFilePath(paths.jsFilePath, options)
+ paths.sourceMapFilePath = GetSourceMapFilePath(paths.jsFilePath, options)
}
}
if forceDtsEmit || options.GetEmitDeclarations() && !isJsonFile {
@@ -74,6 +74,21 @@ func ForEachEmittedFile(host OutputPathsHost, options *core.CompilerOptions, act
return false
}
+func GetOutputJSFileName(inputFileName string, options *core.CompilerOptions, host OutputPathsHost) string {
+ if options.EmitDeclarationOnly.IsTrue() {
+ return ""
+ }
+ outputFileName := GetOutputJSFileNameWorker(inputFileName, options, host)
+ if !tspath.FileExtensionIs(outputFileName, tspath.ExtensionJson) ||
+ tspath.ComparePaths(inputFileName, outputFileName, tspath.ComparePathsOptions{
+ CurrentDirectory: host.GetCurrentDirectory(),
+ UseCaseSensitiveFileNames: host.UseCaseSensitiveFileNames(),
+ }) != 0 {
+ return outputFileName
+ }
+ return ""
+}
+
func GetOutputJSFileNameWorker(inputFileName string, options *core.CompilerOptions, host OutputPathsHost) string {
return tspath.ChangeExtension(
getOutputPathWithoutChangingExtension(inputFileName, options.OutDir, host),
@@ -176,7 +191,7 @@ func getOwnEmitOutputFilePath(fileName string, options *core.CompilerOptions, ho
return emitOutputFilePathWithoutExtension + extension
}
-func getSourceMapFilePath(jsFilePath string, options *core.CompilerOptions) string {
+func GetSourceMapFilePath(jsFilePath string, options *core.CompilerOptions) string {
if options.SourceMap.IsTrue() && !options.InlineSourceMap.IsTrue() {
return jsFilePath + ".map"
}
@@ -195,7 +210,7 @@ func getDeclarationEmitExtensionForPath(fileName string) string {
}
func GetBuildInfoFileName(options *core.CompilerOptions, opts tspath.ComparePathsOptions) string {
- if !options.IsIncremental() && !options.TscBuild.IsTrue() {
+ if !options.IsIncremental() && !options.Build.IsTrue() {
return ""
}
if options.TsBuildInfoFile != "" {
diff --git a/internal/parser/parser.go b/internal/parser/parser.go
index 8378b7abb6..67bb38207c 100644
--- a/internal/parser/parser.go
+++ b/internal/parser/parser.go
@@ -6380,7 +6380,7 @@ func (p *Parser) processPragmasIntoFields(context *ast.SourceFile) {
case typesOk:
var parsed core.ResolutionMode
if resolutionModeOk {
- parsed = parseResolutionMode(resolutionMode.Value, types.Pos(), types.End() /*, reportDiagnostic*/)
+ parsed = parseResolutionMode(resolutionMode.Value, resolutionMode.Pos(), resolutionMode.End() /*, reportDiagnostic*/)
}
context.TypeReferenceDirectives = append(context.TypeReferenceDirectives, &ast.FileReference{
TextRange: types.TextRange,
@@ -6390,13 +6390,13 @@ func (p *Parser) processPragmasIntoFields(context *ast.SourceFile) {
})
case libOk:
context.LibReferenceDirectives = append(context.LibReferenceDirectives, &ast.FileReference{
- TextRange: types.TextRange,
+ TextRange: lib.TextRange,
FileName: lib.Value,
Preserve: preserveOk && preserve.Value == "true",
})
case pathOk:
context.ReferencedFiles = append(context.ReferencedFiles, &ast.FileReference{
- TextRange: types.TextRange,
+ TextRange: path.TextRange,
FileName: path.Value,
Preserve: preserveOk && preserve.Value == "true",
})
diff --git a/internal/printer/emithost.go b/internal/printer/emithost.go
index 901598392f..410729570c 100644
--- a/internal/printer/emithost.go
+++ b/internal/printer/emithost.go
@@ -18,6 +18,6 @@ type EmitHost interface {
WriteFile(fileName string, text string, writeByteOrderMark bool) error
GetEmitModuleFormatOfFile(file ast.HasFileName) core.ModuleKind
GetEmitResolver() EmitResolver
- GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference
+ GetProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference
IsSourceFileFromExternalLibrary(file *ast.SourceFile) bool
}
diff --git a/internal/testutil/harnessutil/harnessutil.go b/internal/testutil/harnessutil/harnessutil.go
index b885996dea..772eb169c0 100644
--- a/internal/testutil/harnessutil/harnessutil.go
+++ b/internal/testutil/harnessutil/harnessutil.go
@@ -3,6 +3,7 @@ package harnessutil
import (
"context"
"fmt"
+ "io"
"io/fs"
"maps"
"os"
@@ -530,10 +531,14 @@ func NewTracerForBaselining(opts tspath.ComparePathsOptions, builder *strings.Bu
}
func (t *TracerForBaselining) Trace(msg string) {
- fmt.Fprintln(t.builder, t.sanitizeTrace(msg))
+ t.TraceWithWriter(t.builder, msg, true)
}
-func (t *TracerForBaselining) sanitizeTrace(msg string) string {
+func (t *TracerForBaselining) TraceWithWriter(w io.Writer, msg string, usePackageJsonCache bool) {
+ fmt.Fprintln(w, t.sanitizeTrace(msg, usePackageJsonCache))
+}
+
+func (t *TracerForBaselining) sanitizeTrace(msg string, usePackageJsonCache bool) string {
// Version
if str := strings.Replace(msg, "'"+core.Version()+"'", "'"+FakeTSVersion+"'", 1); str != msg {
return str
@@ -541,42 +546,48 @@ func (t *TracerForBaselining) sanitizeTrace(msg string) string {
// caching of fs in trace to be replaces with non caching version
if str := strings.TrimSuffix(msg, "' does not exist according to earlier cached lookups."); str != msg {
file := strings.TrimPrefix(str, "File '")
- filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
- if _, has := t.packageJsonCache[filePath]; has {
- return msg
- } else {
- t.packageJsonCache[filePath] = false
- return fmt.Sprintf("File '%s' does not exist.", file)
- }
- }
- if str := strings.TrimSuffix(msg, "' does not exist."); str != msg {
- file := strings.TrimPrefix(str, "File '")
- filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
- if _, has := t.packageJsonCache[filePath]; !has {
- t.packageJsonCache[filePath] = false
- return msg
- } else {
- return fmt.Sprintf("File '%s' does not exist according to earlier cached lookups.", file)
+ if usePackageJsonCache {
+ filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
+ if _, has := t.packageJsonCache[filePath]; has {
+ return msg
+ } else {
+ t.packageJsonCache[filePath] = false
+ }
}
+ return fmt.Sprintf("File '%s' does not exist.", file)
}
if str := strings.TrimSuffix(msg, "' exists according to earlier cached lookups."); str != msg {
file := strings.TrimPrefix(str, "File '")
- filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
- if _, has := t.packageJsonCache[filePath]; has {
- return msg
- } else {
- t.packageJsonCache[filePath] = true
- return fmt.Sprintf("Found 'package.json' at '%s'.", file)
+ if usePackageJsonCache {
+ filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
+ if _, has := t.packageJsonCache[filePath]; has {
+ return msg
+ } else {
+ t.packageJsonCache[filePath] = true
+ }
}
- }
- if str := strings.TrimPrefix(msg, "Found 'package.json' at '"); str != msg {
- file := strings.TrimSuffix(str, "'.")
- filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
- if _, has := t.packageJsonCache[filePath]; !has {
- t.packageJsonCache[filePath] = true
- return msg
- } else {
- return fmt.Sprintf("File '%s' exists according to earlier cached lookups.", file)
+ return fmt.Sprintf("Found 'package.json' at '%s'.", file)
+ }
+ if usePackageJsonCache {
+ if str := strings.TrimSuffix(msg, "' does not exist."); str != msg {
+ file := strings.TrimPrefix(str, "File '")
+ filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
+ if _, has := t.packageJsonCache[filePath]; !has {
+ t.packageJsonCache[filePath] = false
+ return msg
+ } else {
+ return fmt.Sprintf("File '%s' does not exist according to earlier cached lookups.", file)
+ }
+ }
+ if str := strings.TrimPrefix(msg, "Found 'package.json' at '"); str != msg {
+ file := strings.TrimSuffix(str, "'.")
+ filePath := tspath.ToPath(file, t.opts.CurrentDirectory, t.opts.UseCaseSensitiveFileNames)
+ if _, has := t.packageJsonCache[filePath]; !has {
+ t.packageJsonCache[filePath] = true
+ return msg
+ } else {
+ return fmt.Sprintf("File '%s' exists according to earlier cached lookups.", file)
+ }
}
}
return msg
diff --git a/internal/transformers/tstransforms/importelision_test.go b/internal/transformers/tstransforms/importelision_test.go
index 6818a6dc08..3dc5c227cd 100644
--- a/internal/transformers/tstransforms/importelision_test.go
+++ b/internal/transformers/tstransforms/importelision_test.go
@@ -81,7 +81,7 @@ func (p *fakeProgram) GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFi
return ""
}
-func (p *fakeProgram) GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
+func (p *fakeProgram) GetProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
return nil
}
@@ -89,7 +89,7 @@ func (p *fakeProgram) IsSourceFromProjectReference(path tspath.Path) bool {
return false
}
-func (p *fakeProgram) GetSourceAndProjectReference(path tspath.Path) *tsoptions.SourceAndProjectReference {
+func (p *fakeProgram) GetProjectReferenceFromOutputDts(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
return nil
}
diff --git a/internal/tsoptions/commandlineoption.go b/internal/tsoptions/commandlineoption.go
index 35b7541031..6377c316c3 100644
--- a/internal/tsoptions/commandlineoption.go
+++ b/internal/tsoptions/commandlineoption.go
@@ -166,7 +166,7 @@ var commandLineOptionElements = map[string]*CommandLineOption{
// CommandLineOption.EnumMap()
var commandLineOptionEnumMap = map[string]*collections.OrderedMap[string, any]{
- "lib": libMap,
+ "lib": LibMap,
"moduleResolution": moduleResolutionOptionMap,
"module": moduleOptionMap,
"target": targetOptionMap,
diff --git a/internal/tsoptions/commandlineparser.go b/internal/tsoptions/commandlineparser.go
index 0d8d237f55..1eb2691a08 100644
--- a/internal/tsoptions/commandlineparser.go
+++ b/internal/tsoptions/commandlineparser.go
@@ -67,6 +67,56 @@ func ParseCommandLine(
}
}
+func ParseBuildCommandLine(
+ commandLine []string,
+ host ParseConfigHost,
+) *ParsedBuildCommandLine {
+ if commandLine == nil {
+ commandLine = []string{}
+ }
+ parser := parseCommandLineWorker(buildOptionsDidYouMeanDiagnostics, commandLine, host.FS())
+ compilerOptions := &core.CompilerOptions{}
+ for key, value := range parser.options.Entries() {
+ buildOption := BuildNameMap.Get(key)
+ if buildOption == &TscBuildOption || buildOption == CompilerNameMap.Get(key) {
+ ParseCompilerOptions(key, value, compilerOptions)
+ }
+ }
+ result := &ParsedBuildCommandLine{
+ BuildOptions: convertMapToOptions(parser.options, &buildOptionsParser{&core.BuildOptions{}}).BuildOptions,
+ CompilerOptions: compilerOptions,
+ WatchOptions: convertMapToOptions(parser.options, &watchOptionsParser{&core.WatchOptions{}}).WatchOptions,
+ Projects: parser.fileNames,
+ Errors: parser.errors,
+
+ comparePathsOptions: tspath.ComparePathsOptions{
+ UseCaseSensitiveFileNames: host.FS().UseCaseSensitiveFileNames(),
+ CurrentDirectory: host.GetCurrentDirectory(),
+ },
+ }
+
+ if len(result.Projects) == 0 {
+ // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
+ result.Projects = append(result.Projects, ".")
+ }
+
+ // Nonsensical combinations
+ if result.BuildOptions.Clean.IsTrue() && result.BuildOptions.Force.IsTrue() {
+ result.Errors = append(result.Errors, ast.NewCompilerDiagnostic(diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"))
+ }
+ if result.BuildOptions.Clean.IsTrue() && result.BuildOptions.Verbose.IsTrue() {
+ result.Errors = append(result.Errors, ast.NewCompilerDiagnostic(diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"))
+ }
+ if result.BuildOptions.Clean.IsTrue() && result.CompilerOptions.Watch.IsTrue() {
+ result.Errors = append(result.Errors, ast.NewCompilerDiagnostic(diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"))
+ }
+ if result.CompilerOptions.Watch.IsTrue() && result.BuildOptions.Dry.IsTrue() {
+ result.Errors = append(result.Errors, ast.NewCompilerDiagnostic(diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"))
+ }
+
+ return result
+}
+
func parseCommandLineWorker(
parseCommandLineWithDiagnostics *ParseCommandLineWorkerDiagnostics,
commandLine []string,
@@ -116,7 +166,7 @@ func (p *commandLineParser) parseStrings(args []string) {
func getInputOptionName(input string) string {
// removes at most two leading '-' from the input string
- return strings.ToLower(strings.TrimPrefix(strings.TrimPrefix(input, "-"), "-"))
+ return strings.TrimPrefix(strings.TrimPrefix(input, "-"), "-")
}
func (p *commandLineParser) parseResponseFile(fileName string) {
diff --git a/internal/tsoptions/commandlineparser_test.go b/internal/tsoptions/commandlineparser_test.go
index fcd1e780c3..9caf562d17 100644
--- a/internal/tsoptions/commandlineparser_test.go
+++ b/internal/tsoptions/commandlineparser_test.go
@@ -15,6 +15,8 @@ import (
"github.com/microsoft/typescript-go/internal/testutil/baseline"
"github.com/microsoft/typescript-go/internal/testutil/filefixture"
"github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tsoptions/tsoptionstest"
+ "github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
"gotest.tools/v3/assert"
)
@@ -80,7 +82,7 @@ func TestCommandLineParseResult(t *testing.T) {
}
for _, testCase := range parseCommandLineSubScenarios {
- testCase.createSubScenario().assertParseResult(t)
+ testCase.createSubScenario("parseCommandLine").assertParseResult(t)
}
}
@@ -89,7 +91,7 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
repo.SkipIfNoTypeScriptSubmodule(t)
// run test for boolean
- subScenarioInput{"allows setting option type boolean to false", []string{"--composite", "false", "0.ts"}}.createSubScenario().assertParseResult(t)
+ subScenarioInput{"allows setting option type boolean to false", []string{"--composite", "false", "0.ts"}}.createSubScenario("parseCommandLine").assertParseResult(t)
verifyNullSubScenarios := []verifyNull{
{
@@ -114,6 +116,7 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
for _, verifyNullCase := range verifyNullSubScenarios {
createSubScenario(
+ "parseCommandLine",
verifyNullCase.subScenario+" allows setting it to null",
[]string{"--" + verifyNullCase.optionName, "null", "0.ts"},
verifyNullCase.optDecls,
@@ -121,6 +124,7 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
if verifyNullCase.nonNullValue != "" {
createSubScenario(
+ "parseCommandLine",
verifyNullCase.subScenario+" errors if non null value is passed",
[]string{"--" + verifyNullCase.optionName, verifyNullCase.nonNullValue, "0.ts"},
verifyNullCase.optDecls,
@@ -128,12 +132,14 @@ func TestParseCommandLineVerifyNull(t *testing.T) {
}
createSubScenario(
+ "parseCommandLine",
verifyNullCase.subScenario+" errors if its followed by another option",
[]string{"0.ts", "--strictNullChecks", "--" + verifyNullCase.optionName},
verifyNullCase.optDecls,
).assertParseResult(t)
createSubScenario(
+ "parseCommandLine",
verifyNullCase.subScenario+" errors if its last option",
[]string{"0.ts", "--" + verifyNullCase.optionName},
verifyNullCase.optDecls,
@@ -195,10 +201,6 @@ func (f commandLineSubScenario) assertParseResult(t *testing.T) {
})
}
-func (f *commandLineSubScenario) getBaselineName() (baseline.Options, string) {
- return baseline.Options{Subfolder: "tsoptions/commandLineParsing"}, f.testName
-}
-
func parseExistingCompilerBaseline(t *testing.T, baseline string) *TestCommandLineParser {
_, rest, _ := strings.Cut(baseline, "CompilerOptions::\n")
compilerOptions, rest, watchFound := strings.Cut(rest, "\nWatchOptions::\n")
@@ -243,27 +245,112 @@ func formatNewBaseline(
return formatted.String()
}
-// todo: --build not implemented
-// func parseExistingBuildBaseline(baseline string) *TestCommandLineParser {
-// _, rest, _ := strings.Cut(baseline, "BuildOptions::\n")
-// buildOptions, rest, _ := strings.Cut(rest, "\nWatchOptions::\n")
-// _, rest, _ = strings.Cut(rest, "\nProjects::\n")
-// fileNames, errors, _ := strings.Cut(rest, "\nErrors::\n")
+func (f commandLineSubScenario) assertBuildParseResult(t *testing.T) {
+ t.Helper()
+ t.Run(f.testName, func(t *testing.T) {
+ t.Parallel()
+ originalBaseline := f.baseline.ReadFile(t)
+ tsBaseline := parseExistingCompilerBaselineBuild(t, originalBaseline)
+
+ // f.workerDiagnostic is either defined or set to default pointer in `createSubScenario`
+ parsed := tsoptions.ParseBuildCommandLine(f.commandLine, &tsoptionstest.VfsParseConfigHost{
+ Vfs: osvfs.FS(),
+ CurrentDirectory: tspath.NormalizeSlashes(repo.TypeScriptSubmodulePath),
+ })
+
+ newBaselineProjects := strings.Join(parsed.Projects, ",")
+ assert.Equal(t, tsBaseline.projects, newBaselineProjects)
+
+ o, _ := json.Marshal(parsed.BuildOptions)
+ newParsedBuildOptions := &core.BuildOptions{}
+ e := json.Unmarshal(o, newParsedBuildOptions)
+ assert.NilError(t, e)
+ assert.DeepEqual(t, tsBaseline.options, newParsedBuildOptions, cmpopts.IgnoreUnexported(core.BuildOptions{}))
+
+ compilerOpts, _ := json.Marshal(parsed.CompilerOptions)
+ newParsedCompilerOptions := &core.CompilerOptions{}
+ e = json.Unmarshal(compilerOpts, newParsedCompilerOptions)
+ assert.NilError(t, e)
+ assert.DeepEqual(t, tsBaseline.compilerOptions, newParsedCompilerOptions, cmpopts.IgnoreUnexported(core.CompilerOptions{}))
+
+ newParsedWatchOptions := core.WatchOptions{}
+ e = json.Unmarshal(o, &newParsedWatchOptions)
+ assert.NilError(t, e)
+
+ // !!! useful for debugging but will not pass due to `none` as enum options
+ // assert.DeepEqual(t, tsBaseline.watchoptions, newParsedWatchOptions)
+
+ var formattedErrors strings.Builder
+ diagnosticwriter.WriteFormatDiagnostics(&formattedErrors, parsed.Errors, &diagnosticwriter.FormattingOptions{NewLine: "\n"})
+ newBaselineErrors := formattedErrors.String()
+
+ // !!!
+ // useful for debugging--compares the new errors with the old errors. currently will NOT pass because of unimplemented options, not completely identical enum options, etc
+ // assert.Equal(t, tsBaseline.errors, newBaselineErrors)
+
+ baseline.Run(t, f.testName+".js", formatNewBaselineBuild(f.commandLine, o, compilerOpts, newBaselineProjects, newBaselineErrors), baseline.Options{Subfolder: "tsoptions/commandLineParsing"})
+ })
+}
+
+func parseExistingCompilerBaselineBuild(t *testing.T, baseline string) *TestCommandLineParserBuild {
+ _, rest, _ := strings.Cut(baseline, "buildOptions::\n")
+ buildOptions, rest, watchFound := strings.Cut(rest, "\nWatchOptions::\n")
+ watchOptions, rest, _ := strings.Cut(rest, "\nProjects::\n")
+ projects, errors, _ := strings.Cut(rest, "\nErrors::\n")
+
+ baselineBuildOptions := &core.BuildOptions{}
+ e := json.Unmarshal([]byte(buildOptions), &baselineBuildOptions)
+ assert.NilError(t, e)
+
+ baselineCompilerOptions := &core.CompilerOptions{}
+ e = json.Unmarshal([]byte(buildOptions), &baselineCompilerOptions)
+ assert.NilError(t, e)
-// // todo: change CompilerOptions to buildoptions
-// baselineOptions := &core.CompilerOptions{}
-// json.Unmarshal([]byte(buildOptions), &baselineOptions)
+ baselineWatchOptions := &core.WatchOptions{}
+ if watchFound && watchOptions != "" {
+ e2 := json.Unmarshal([]byte(watchOptions), &baselineWatchOptions)
+ assert.NilError(t, e2)
+ }
+
+ return &TestCommandLineParserBuild{
+ options: baselineBuildOptions,
+ compilerOptions: baselineCompilerOptions,
+ watchoptions: baselineWatchOptions,
+ projects: projects,
+ errors: errors,
+ }
+}
-// var parser = TestCommandLineParser{
-// options: *baselineOptions,
-// fileNames: fileNames,
-// errors: errors,
-// }
-// return &parser
-// }
+func formatNewBaselineBuild(
+ commandLine []string,
+ opts []byte,
+ compilerOpts []byte,
+ projects string,
+ errors string,
+) string {
+ var formatted strings.Builder
+ formatted.WriteString("Args::\n")
+ if len(commandLine) == 0 {
+ formatted.WriteString("[]")
+ } else {
+ formatted.WriteString("[\"" + strings.Join(commandLine, "\", \"") + "\"]")
+ }
+ formatted.WriteString("\n\nbuildOptions::\n")
+ formatted.Write(opts)
+ formatted.WriteString("\n\ncompilerOptions::\n")
+ formatted.Write(compilerOpts)
+ // todo: watch options not implemented
+ // formatted.WriteString("WatchOptions::\n")
+ formatted.WriteString("\n\nProjects::\n")
+ formatted.WriteString(projects)
+ formatted.WriteString("\n\nErrors::\n")
+ formatted.WriteString(errors)
+ return formatted.String()
+}
-func createSubScenario(subScenarioName string, commandline []string, opts ...[]*tsoptions.CommandLineOption) *commandLineSubScenario {
- baselineFileName := "tests/baselines/reference/config/commandLineParsing/parseCommandLine/" + subScenarioName + ".js"
+func createSubScenario(scenarioKind string, subScenarioName string, commandline []string, opts ...[]*tsoptions.CommandLineOption) *commandLineSubScenario {
+ subScenarioName = scenarioKind + "/" + subScenarioName
+ baselineFileName := "tests/baselines/reference/config/commandLineParsing/" + subScenarioName + ".js"
result := &commandLineSubScenario{
filefixture.FromFile(subScenarioName, filepath.Join(repo.TypeScriptSubmodulePath, baselineFileName)),
@@ -282,8 +369,8 @@ type subScenarioInput struct {
commandLineArgs []string
}
-func (f subScenarioInput) createSubScenario() *commandLineSubScenario {
- return createSubScenario(f.name, f.commandLineArgs)
+func (f subScenarioInput) createSubScenario(scenarioKind string) *commandLineSubScenario {
+ return createSubScenario(scenarioKind, f.name, f.commandLineArgs)
}
type commandLineSubScenario struct {
@@ -306,6 +393,47 @@ type TestCommandLineParser struct {
fileNames, errors string
}
+type TestCommandLineParserBuild struct {
+ options *core.BuildOptions
+ compilerOptions *core.CompilerOptions
+ watchoptions *core.WatchOptions
+ projects, errors string
+}
+
+func TestParseBuildCommandLine(t *testing.T) {
+ t.Parallel()
+ repo.SkipIfNoTypeScriptSubmodule(t)
+
+ parseCommandLineSubScenarios := []*subScenarioInput{
+ {"parse build without any options ", []string{}},
+ {"Parse multiple options", []string{"--verbose", "--force", "tests"}},
+ {"Parse option with invalid option", []string{"--verbose", "--invalidOption"}},
+ {"Parse multiple flags with input projects at the end", []string{"--force", "--verbose", "src", "tests"}},
+ {"Parse multiple flags with input projects in the middle", []string{"--force", "src", "tests", "--verbose"}},
+ {"Parse multiple flags with input projects in the beginning", []string{"src", "tests", "--force", "--verbose"}},
+ {"parse build with --incremental", []string{"--incremental", "tests"}},
+ {"parse build with --locale en-us", []string{"--locale", "en-us", "src"}},
+ {"parse build with --tsBuildInfoFile", []string{"--tsBuildInfoFile", "build.tsbuildinfo", "tests"}},
+ {"reports other common may not be used with --build flags", []string{"--strict"}},
+ {`--clean and --force together is invalid`, []string{"--clean", "--force"}},
+ {`--clean and --verbose together is invalid`, []string{"--clean", "--verbose"}},
+ {`--clean and --watch together is invalid`, []string{"--clean", "--watch"}},
+ {`--watch and --dry together is invalid`, []string{"--watch", "--dry"}},
+ {"parse --watchFile", []string{"--watchFile", "UseFsEvents", "--verbose"}},
+ {"parse --watchDirectory", []string{"--watchDirectory", "FixedPollingInterval", "--verbose"}},
+ {"parse --fallbackPolling", []string{"--fallbackPolling", "PriorityInterval", "--verbose"}},
+ {"parse --synchronousWatchDirectory", []string{"--synchronousWatchDirectory", "--verbose"}},
+ {"errors on missing argument", []string{"--verbose", "--fallbackPolling"}},
+ {"errors on invalid excludeDirectories", []string{"--excludeDirectories", "**/../*"}},
+ {"parse --excludeFiles", []string{"--excludeFiles", "**/temp/*.ts"}},
+ {"errors on invalid excludeFiles", []string{"--excludeFiles", "**/../*"}},
+ }
+
+ for _, testCase := range parseCommandLineSubScenarios {
+ testCase.createSubScenario("parseBuildOptions").assertBuildParseResult(t)
+ }
+}
+
func TestAffectsBuildInfo(t *testing.T) {
t.Parallel()
t.Run("should have affectsBuildInfo true for every option with affectsSemanticDiagnostics", func(t *testing.T) {
diff --git a/internal/tsoptions/decls_test.go b/internal/tsoptions/decls_test.go
index 38ef65a8d3..221cc027ce 100644
--- a/internal/tsoptions/decls_test.go
+++ b/internal/tsoptions/decls_test.go
@@ -26,7 +26,7 @@ func TestCompilerOptionsDeclaration(t *testing.T) {
"noEmitForJsFiles",
"pathsBasePath",
"suppressOutputPathCheck",
- "tscBuild",
+ "build",
}
internalOptionsMap := make(map[string]string)
diff --git a/internal/tsoptions/declscompiler.go b/internal/tsoptions/declscompiler.go
index 11b6335ea1..725b68dc3e 100644
--- a/internal/tsoptions/declscompiler.go
+++ b/internal/tsoptions/declscompiler.go
@@ -10,8 +10,8 @@ import (
var OptionsDeclarations = slices.Concat(commonOptionsWithBuild, optionsForCompiler)
-var optionsForCompiler = []*CommandLineOption{
- //******* commandOptionsWithoutBuild *******
+var commonOptionsWithBuild = []*CommandLineOption{
+ //******* commonOptionsWithBuild *******
{
Name: "help",
ShortName: "h",
@@ -235,8 +235,8 @@ var optionsForCompiler = []*CommandLineOption{
},
}
-var commonOptionsWithBuild = []*CommandLineOption{
- //******* commandOptionsWithoutBuild *******
+var optionsForCompiler = []*CommandLineOption{
+ //******* compilerOptions not common with --build *******
// CommandLine only options
{
diff --git a/internal/tsoptions/enummaps.go b/internal/tsoptions/enummaps.go
index 297081deaa..89a9ba9bfd 100644
--- a/internal/tsoptions/enummaps.go
+++ b/internal/tsoptions/enummaps.go
@@ -8,7 +8,7 @@ import (
"github.com/microsoft/typescript-go/internal/tspath"
)
-var libMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{
+var LibMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, any]{
// JavaScript only
{Key: "es5", Value: "lib.es5.d.ts"},
{Key: "es6", Value: "lib.es2015.d.ts"},
@@ -113,8 +113,8 @@ var libMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, an
})
var (
- Libs = slices.Collect(libMap.Keys())
- LibFilesSet = collections.NewSetFromItems(core.Map(slices.Collect(libMap.Values()), func(s any) string { return s.(string) })...)
+ Libs = slices.Collect(LibMap.Keys())
+ LibFilesSet = collections.NewSetFromItems(core.Map(slices.Collect(LibMap.Values()), func(s any) string { return s.(string) })...)
)
func GetLibFileName(libName string) (string, bool) {
@@ -123,7 +123,7 @@ func GetLibFileName(libName string) (string, bool) {
if LibFilesSet.Has(libName) {
return libName, true
}
- lib, ok := libMap.Get(libName)
+ lib, ok := LibMap.Get(libName)
if !ok {
return "", false
}
diff --git a/internal/tsoptions/errors.go b/internal/tsoptions/errors.go
index ef56e1ddb3..bca802b649 100644
--- a/internal/tsoptions/errors.go
+++ b/internal/tsoptions/errors.go
@@ -97,6 +97,8 @@ func extraKeyDiagnostics(s string) *diagnostics.Message {
return diagnostics.Unknown_watch_option_0
case "typeAcquisition":
return diagnostics.Unknown_type_acquisition_option_0
+ case "buildOptions":
+ return diagnostics.Unknown_build_option_0
default:
return nil
}
diff --git a/internal/tsoptions/namemap.go b/internal/tsoptions/namemap.go
index e199577f87..31a8b98d48 100644
--- a/internal/tsoptions/namemap.go
+++ b/internal/tsoptions/namemap.go
@@ -46,6 +46,7 @@ func (nm *NameMap) GetFromShort(shortName string) *CommandLineOption {
}
func (nm *NameMap) GetOptionDeclarationFromName(optionName string, allowShort bool) *CommandLineOption {
+ optionName = strings.ToLower(optionName)
// Try to translate short option names to their full equivalents.
if allowShort {
short := nm.shortOptionNames[optionName]
diff --git a/internal/tsoptions/parsedbuildcommandline.go b/internal/tsoptions/parsedbuildcommandline.go
new file mode 100644
index 0000000000..8a777b8c15
--- /dev/null
+++ b/internal/tsoptions/parsedbuildcommandline.go
@@ -0,0 +1,33 @@
+package tsoptions
+
+import (
+ "sync"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/tspath"
+)
+
+type ParsedBuildCommandLine struct {
+ BuildOptions *core.BuildOptions `json:"buildOptions"`
+ CompilerOptions *core.CompilerOptions `json:"compilerOptions"`
+ WatchOptions *core.WatchOptions `json:"watchOptions"`
+ Projects []string `json:"projects"`
+ Errors []*ast.Diagnostic `json:"errors"`
+
+ comparePathsOptions tspath.ComparePathsOptions
+
+ resolvedProjectPaths []string
+ resolvedProjectPathsOnce sync.Once
+}
+
+func (p *ParsedBuildCommandLine) ResolvedProjectPaths() []string {
+ p.resolvedProjectPathsOnce.Do(func() {
+ p.resolvedProjectPaths = core.Map(p.Projects, func(project string) string {
+ return core.ResolveConfigFileNameOfProjectReference(
+ tspath.ResolvePath(p.comparePathsOptions.CurrentDirectory, project),
+ )
+ })
+ })
+ return p.resolvedProjectPaths
+}
diff --git a/internal/tsoptions/parsedcommandline.go b/internal/tsoptions/parsedcommandline.go
index a265f7dc87..68e8d46e6b 100644
--- a/internal/tsoptions/parsedcommandline.go
+++ b/internal/tsoptions/parsedcommandline.go
@@ -27,9 +27,9 @@ type ParsedCommandLine struct {
wildcardDirectories map[string]bool
extraFileExtensions []FileExtensionInfo
- sourceAndOutputMapsOnce sync.Once
- sourceToOutput map[tspath.Path]*OutputDtsAndProjectReference
- outputDtsToSource map[tspath.Path]*SourceAndProjectReference
+ sourceAndOutputMapsOnce sync.Once
+ sourceToProjectReference map[tspath.Path]*SourceOutputAndProjectReference
+ outputDtsToProjectReference map[tspath.Path]*SourceOutputAndProjectReference
commonSourceDirectory string
commonSourceDirectoryOnce sync.Once
@@ -38,12 +38,8 @@ type ParsedCommandLine struct {
resolvedProjectReferencePathsOnce sync.Once
}
-type SourceAndProjectReference struct {
- Source string
- Resolved *ParsedCommandLine
-}
-
-type OutputDtsAndProjectReference struct {
+type SourceOutputAndProjectReference struct {
+ Source string
OutputDts string
Resolved *ParsedCommandLine
}
@@ -60,34 +56,33 @@ func (p *ParsedCommandLine) ConfigName() string {
return p.ConfigFile.SourceFile.FileName()
}
-func (p *ParsedCommandLine) SourceToOutput() map[tspath.Path]*OutputDtsAndProjectReference {
- return p.sourceToOutput
+func (p *ParsedCommandLine) SourceToProjectReference() map[tspath.Path]*SourceOutputAndProjectReference {
+ return p.sourceToProjectReference
}
-func (p *ParsedCommandLine) OutputDtsToSource() map[tspath.Path]*SourceAndProjectReference {
- return p.outputDtsToSource
+func (p *ParsedCommandLine) OutputDtsToProjectReference() map[tspath.Path]*SourceOutputAndProjectReference {
+ return p.outputDtsToProjectReference
}
func (p *ParsedCommandLine) ParseInputOutputNames() {
p.sourceAndOutputMapsOnce.Do(func() {
- sourceToOutput := map[tspath.Path]*OutputDtsAndProjectReference{}
- outputDtsToSource := map[tspath.Path]*SourceAndProjectReference{}
+ sourceToOutput := map[tspath.Path]*SourceOutputAndProjectReference{}
+ outputDtsToSource := map[tspath.Path]*SourceOutputAndProjectReference{}
for outputDts, source := range p.GetOutputDeclarationFileNames() {
path := tspath.ToPath(source, p.GetCurrentDirectory(), p.UseCaseSensitiveFileNames())
- if outputDts != "" {
- outputDtsToSource[tspath.ToPath(outputDts, p.GetCurrentDirectory(), p.UseCaseSensitiveFileNames())] = &SourceAndProjectReference{
- Source: source,
- Resolved: p,
- }
- }
- sourceToOutput[path] = &OutputDtsAndProjectReference{
+ projectReference := &SourceOutputAndProjectReference{
+ Source: source,
OutputDts: outputDts,
Resolved: p,
}
+ if outputDts != "" {
+ outputDtsToSource[tspath.ToPath(outputDts, p.GetCurrentDirectory(), p.UseCaseSensitiveFileNames())] = projectReference
+ }
+ sourceToOutput[path] = projectReference
}
- p.outputDtsToSource = outputDtsToSource
- p.sourceToOutput = sourceToOutput
+ p.outputDtsToProjectReference = outputDtsToSource
+ p.sourceToProjectReference = sourceToOutput
})
}
@@ -135,6 +130,52 @@ func (p *ParsedCommandLine) GetOutputDeclarationFileNames() iter.Seq2[string, st
}
}
+func (p *ParsedCommandLine) GetOutputFileNames() iter.Seq[string] {
+ return func(yield func(outputName string) bool) {
+ for _, fileName := range p.ParsedConfig.FileNames {
+ if tspath.IsDeclarationFileName(fileName) {
+ continue
+ }
+ jsFileName := outputpaths.GetOutputJSFileName(fileName, p.CompilerOptions(), p)
+ isJson := tspath.FileExtensionIs(fileName, tspath.ExtensionJson)
+ if jsFileName != "" {
+ if !yield(jsFileName) {
+ return
+ }
+ if !isJson {
+ sourceMap := outputpaths.GetSourceMapFilePath(jsFileName, p.CompilerOptions())
+ if sourceMap != "" {
+ if !yield(sourceMap) {
+ return
+ }
+ }
+ }
+ }
+ if isJson {
+ continue
+ }
+ if p.CompilerOptions().GetEmitDeclarations() {
+ dtsFileName := outputpaths.GetOutputDeclarationFileNameWorker(fileName, p.CompilerOptions(), p)
+ if dtsFileName != "" {
+ if !yield(dtsFileName) {
+ return
+ }
+ if p.CompilerOptions().GetAreDeclarationMapsEnabled() {
+ declarationMap := dtsFileName + ".map"
+ if !yield(declarationMap) {
+ return
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+func (p *ParsedCommandLine) GetBuildInfoFileName() string {
+ return outputpaths.GetBuildInfoFileName(p.CompilerOptions(), p.comparePathsOptions)
+}
+
// WildcardDirectories returns the cached wildcard directories, initializing them if needed
func (p *ParsedCommandLine) WildcardDirectories() map[string]bool {
if p == nil {
@@ -179,10 +220,6 @@ func (p *ParsedCommandLine) CompilerOptions() *core.CompilerOptions {
return p.ParsedConfig.CompilerOptions
}
-func (p *ParsedCommandLine) GetBuildInfoFileName() string {
- return outputpaths.GetBuildInfoFileName(p.CompilerOptions(), p.comparePathsOptions)
-}
-
func (p *ParsedCommandLine) SetTypeAcquisition(o *core.TypeAcquisition) {
p.ParsedConfig.TypeAcquisition = o
}
@@ -202,14 +239,7 @@ func (p *ParsedCommandLine) ProjectReferences() []*core.ProjectReference {
func (p *ParsedCommandLine) ResolvedProjectReferencePaths() []string {
p.resolvedProjectReferencePathsOnce.Do(func() {
- if p.ParsedConfig.ProjectReferences == nil {
- return
- }
- resolvedProjectReferencePaths := make([]string, 0, len(p.ParsedConfig.ProjectReferences))
- for _, ref := range p.ParsedConfig.ProjectReferences {
- resolvedProjectReferencePaths = append(resolvedProjectReferencePaths, core.ResolveProjectReferencePath(ref))
- }
- p.resolvedProjectReferencePaths = resolvedProjectReferencePaths
+ p.resolvedProjectReferencePaths = core.Map(p.ParsedConfig.ProjectReferences, core.ResolveProjectReferencePath)
})
return p.resolvedProjectReferencePaths
}
diff --git a/internal/tsoptions/parsinghelpers.go b/internal/tsoptions/parsinghelpers.go
index 8ddcf6194d..bf16518be2 100644
--- a/internal/tsoptions/parsinghelpers.go
+++ b/internal/tsoptions/parsinghelpers.go
@@ -156,6 +156,18 @@ func (o *typeAcquisitionParser) UnknownOptionDiagnostic() *diagnostics.Message {
return extraKeyDiagnostics("typeAcquisition")
}
+type buildOptionsParser struct {
+ *core.BuildOptions
+}
+
+func (o *buildOptionsParser) ParseOption(key string, value any) []*ast.Diagnostic {
+ return ParseBuildOptions(key, value, o.BuildOptions)
+}
+
+func (o *buildOptionsParser) UnknownOptionDiagnostic() *diagnostics.Message {
+ return extraKeyDiagnostics("buildOptions")
+}
+
func ParseCompilerOptions(key string, value any, allOptions *core.CompilerOptions) []*ast.Diagnostic {
if value == nil {
return nil
@@ -391,8 +403,6 @@ func parseCompilerOptions(key string, value any, allOptions *core.CompilerOption
allOptions.TsBuildInfoFile = parseString(value)
case "typeRoots":
allOptions.TypeRoots = parseStringArray(value)
- case "tscBuild":
- allOptions.TscBuild = parseTristate(value)
case "types":
allOptions.Types = parseStringArray(value)
case "useDefineForClassFields":
@@ -496,6 +506,32 @@ func ParseTypeAcquisition(key string, value any, allOptions *core.TypeAcquisitio
return nil
}
+func ParseBuildOptions(key string, value any, allOptions *core.BuildOptions) []*ast.Diagnostic {
+ if value == nil {
+ return nil
+ }
+ if allOptions == nil {
+ return nil
+ }
+ option := BuildNameMap.Get(key)
+ if option != nil {
+ key = option.Name
+ }
+ switch key {
+ case "clean":
+ allOptions.Clean = parseTristate(value)
+ case "dry":
+ allOptions.Dry = parseTristate(value)
+ case "force":
+ allOptions.Force = parseTristate(value)
+ case "stopBuildOnErrors":
+ allOptions.StopBuildOnErrors = parseTristate(value)
+ case "verbose":
+ allOptions.Verbose = parseTristate(value)
+ }
+ return nil
+}
+
// mergeCompilerOptions merges the source compiler options into the target compiler options
// with optional awareness of explicitly set null values in the raw JSON.
// Fields in the source options will overwrite the corresponding fields in the target options,
@@ -576,7 +612,9 @@ func ConvertOptionToAbsolutePath(o string, v any, optionMap CommandLineOptionNam
}
}
} else if option.IsFilePath {
- return tspath.GetNormalizedAbsolutePath(v.(string), cwd), true
+ if value, ok := v.(string); ok {
+ return tspath.GetNormalizedAbsolutePath(value, cwd), true
+ }
}
return nil, false
}
diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go
index 81edaf6bd1..79e5cbbbb1 100644
--- a/internal/tsoptions/tsconfigparsing.go
+++ b/internal/tsoptions/tsconfigparsing.go
@@ -1282,9 +1282,10 @@ func parseJsonConfigFileContentWorker(
}
getProjectReferences := func(basePath string) []*core.ProjectReference {
- var projectReferences []*core.ProjectReference = []*core.ProjectReference{}
+ var projectReferences []*core.ProjectReference
newReferencesOfRaw := getPropFromRaw("references", func(element any) bool { return reflect.TypeOf(element) == orderedMapType }, "object")
if newReferencesOfRaw.sliceValue != nil {
+ projectReferences = []*core.ProjectReference{}
for _, reference := range newReferencesOfRaw.sliceValue {
for _, ref := range parseProjectReference(reference) {
if reflect.TypeOf(ref.Path).Kind() != reflect.String {
diff --git a/internal/vfs/cachedvfs/cachedvfs.go b/internal/vfs/cachedvfs/cachedvfs.go
index 0e284fe043..6fcc3d92f4 100644
--- a/internal/vfs/cachedvfs/cachedvfs.go
+++ b/internal/vfs/cachedvfs/cachedvfs.go
@@ -2,6 +2,7 @@ package cachedvfs
import (
"sync/atomic"
+ "time"
"github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/vfs"
@@ -116,10 +117,14 @@ func (fsys *FS) Remove(path string) error {
return fsys.fs.Remove(path)
}
+func (fsys *FS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ return fsys.fs.Chtimes(path, aTime, mTime)
+}
+
func (fsys *FS) Stat(path string) vfs.FileInfo {
if fsys.enabled.Load() {
if ret, ok := fsys.statCache.Load(path); ok {
- return ret.(vfs.FileInfo)
+ return ret
}
}
@@ -141,5 +146,6 @@ func (fsys *FS) WalkDir(root string, walkFn vfs.WalkDirFunc) error {
}
func (fsys *FS) WriteFile(path string, data string, writeByteOrderMark bool) error {
+ // !!! sheetal this needs update to caches or not?
return fsys.fs.WriteFile(path, data, writeByteOrderMark)
}
diff --git a/internal/vfs/iovfs/iofs.go b/internal/vfs/iovfs/iofs.go
index a5289d4f0b..3c3c4bd7c9 100644
--- a/internal/vfs/iovfs/iofs.go
+++ b/internal/vfs/iovfs/iofs.go
@@ -4,6 +4,7 @@ import (
"fmt"
"io/fs"
"strings"
+ "time"
"github.com/microsoft/typescript-go/internal/stringutil"
"github.com/microsoft/typescript-go/internal/tspath"
@@ -22,6 +23,7 @@ type WritableFS interface {
MkdirAll(path string, perm fs.FileMode) error
// Removes `path` and all its contents. Will return the first error it encounters.
Remove(path string) error
+ Chtimes(path string, aTime time.Time, mTime time.Time) error
}
type FsWithSys interface {
@@ -61,6 +63,7 @@ func From(fsys fs.FS, useCaseSensitiveFileNames bool) FsWithSys {
var writeFile func(path string, content string, writeByteOrderMark bool) error
var mkdirAll func(path string) error
var remove func(path string) error
+ var chtimes func(path string, aTime time.Time, mTime time.Time) error
if fsys, ok := fsys.(WritableFS); ok {
writeFile = func(path string, content string, writeByteOrderMark bool) error {
rest, _ := strings.CutPrefix(path, "/")
@@ -80,6 +83,10 @@ func From(fsys fs.FS, useCaseSensitiveFileNames bool) FsWithSys {
rest, _ := strings.CutPrefix(path, "/")
return fsys.Remove(rest)
}
+ chtimes = func(path string, aTime time.Time, mTime time.Time) error {
+ rest, _ := strings.CutPrefix(path, "/")
+ return fsys.Chtimes(rest, aTime, mTime)
+ }
} else {
writeFile = func(string, string, bool) error {
panic("writeFile not supported")
@@ -90,6 +97,9 @@ func From(fsys fs.FS, useCaseSensitiveFileNames bool) FsWithSys {
remove = func(string) error {
panic("remove not supported")
}
+ chtimes = func(string, time.Time, time.Time) error {
+ panic("chtimes not supported")
+ }
}
return &ioFS{
@@ -112,6 +122,7 @@ func From(fsys fs.FS, useCaseSensitiveFileNames bool) FsWithSys {
writeFile: writeFile,
mkdirAll: mkdirAll,
remove: remove,
+ chtimes: chtimes,
fsys: fsys,
}
}
@@ -124,6 +135,7 @@ type ioFS struct {
writeFile func(path string, content string, writeByteOrderMark bool) error
mkdirAll func(path string) error
remove func(path string) error
+ chtimes func(path string, aTime time.Time, mTime time.Time) error
fsys fs.FS
}
@@ -163,6 +175,11 @@ func (vfs *ioFS) Remove(path string) error {
return vfs.remove(path)
}
+func (vfs *ioFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ _ = internal.RootLength(path) // Assert path is rooted
+ return vfs.chtimes(path, aTime, mTime)
+}
+
func (vfs *ioFS) Realpath(path string) string {
root, rest := internal.SplitPath(path)
// splitPath normalizes the path into parts (e.g. "c:/foo/bar" -> "c:/", "foo/bar")
diff --git a/internal/vfs/osvfs/os.go b/internal/vfs/osvfs/os.go
index 47439b59d1..d811d6ff71 100644
--- a/internal/vfs/osvfs/os.go
+++ b/internal/vfs/osvfs/os.go
@@ -6,6 +6,7 @@ import (
"path/filepath"
"runtime"
"strings"
+ "time"
"unicode"
"github.com/microsoft/typescript-go/internal/tspath"
@@ -170,3 +171,7 @@ func (vfs *osFS) Remove(path string) error {
// todo: #701 add retry mechanism?
return os.RemoveAll(path)
}
+
+func (vfs *osFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ return os.Chtimes(path, aTime, mTime)
+}
diff --git a/internal/vfs/vfs.go b/internal/vfs/vfs.go
index f2e05340e7..f50309b4d4 100644
--- a/internal/vfs/vfs.go
+++ b/internal/vfs/vfs.go
@@ -2,6 +2,7 @@ package vfs
import (
"io/fs"
+ "time"
)
//go:generate go tool github.com/matryer/moq -fmt goimports -out vfsmock/mock_generated.go -pkg vfsmock . FS
@@ -24,6 +25,9 @@ type FS interface {
// Removes `path` and all its contents. Will return the first error it encounters.
Remove(path string) error
+ // Chtimes changes the access and modification times of the named
+ Chtimes(path string, aTime time.Time, mTime time.Time) error
+
// DirectoryExists returns true if the path is a directory.
DirectoryExists(path string) bool
diff --git a/internal/vfs/vfsmock/mock_generated.go b/internal/vfs/vfsmock/mock_generated.go
index f18d46dd4e..88b875abc7 100644
--- a/internal/vfs/vfsmock/mock_generated.go
+++ b/internal/vfs/vfsmock/mock_generated.go
@@ -5,6 +5,7 @@ package vfsmock
import (
"sync"
+ "time"
"github.com/microsoft/typescript-go/internal/vfs"
)
@@ -19,6 +20,9 @@ var _ vfs.FS = &FSMock{}
//
// // make and configure a mocked vfs.FS
// mockedFS := &FSMock{
+// ChtimesFunc: func(path string, aTime time.Time, mTime time.Time) error {
+// panic("mock out the Chtimes method")
+// },
// DirectoryExistsFunc: func(path string) bool {
// panic("mock out the DirectoryExists method")
// },
@@ -56,6 +60,9 @@ var _ vfs.FS = &FSMock{}
//
// }
type FSMock struct {
+ // ChtimesFunc mocks the Chtimes method.
+ ChtimesFunc func(path string, aTime time.Time, mTime time.Time) error
+
// DirectoryExistsFunc mocks the DirectoryExists method.
DirectoryExistsFunc func(path string) bool
@@ -88,6 +95,15 @@ type FSMock struct {
// calls tracks calls to the methods.
calls struct {
+ // Chtimes holds details about calls to the Chtimes method.
+ Chtimes []struct {
+ // Path is the path argument value.
+ Path string
+ // ATime is the aTime argument value.
+ ATime time.Time
+ // MTime is the mTime argument value.
+ MTime time.Time
+ }
// DirectoryExists holds details about calls to the DirectoryExists method.
DirectoryExists []struct {
// Path is the path argument value.
@@ -142,6 +158,7 @@ type FSMock struct {
WriteByteOrderMark bool
}
}
+ lockChtimes sync.RWMutex
lockDirectoryExists sync.RWMutex
lockFileExists sync.RWMutex
lockGetAccessibleEntries sync.RWMutex
@@ -154,6 +171,46 @@ type FSMock struct {
lockWriteFile sync.RWMutex
}
+// Chtimes calls ChtimesFunc.
+func (mock *FSMock) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ if mock.ChtimesFunc == nil {
+ panic("FSMock.ChtimesFunc: method is nil but FS.Chtimes was just called")
+ }
+ callInfo := struct {
+ Path string
+ ATime time.Time
+ MTime time.Time
+ }{
+ Path: path,
+ ATime: aTime,
+ MTime: mTime,
+ }
+ mock.lockChtimes.Lock()
+ mock.calls.Chtimes = append(mock.calls.Chtimes, callInfo)
+ mock.lockChtimes.Unlock()
+ return mock.ChtimesFunc(path, aTime, mTime)
+}
+
+// ChtimesCalls gets all the calls that were made to Chtimes.
+// Check the length with:
+//
+// len(mockedFS.ChtimesCalls())
+func (mock *FSMock) ChtimesCalls() []struct {
+ Path string
+ ATime time.Time
+ MTime time.Time
+} {
+ var calls []struct {
+ Path string
+ ATime time.Time
+ MTime time.Time
+ }
+ mock.lockChtimes.RLock()
+ calls = mock.calls.Chtimes
+ mock.lockChtimes.RUnlock()
+ return calls
+}
+
// DirectoryExists calls DirectoryExistsFunc.
func (mock *FSMock) DirectoryExists(path string) bool {
if mock.DirectoryExistsFunc == nil {
diff --git a/internal/vfs/vfsmock/wrapper.go b/internal/vfs/vfsmock/wrapper.go
index 02ba3acd2f..9ca2fc7a4a 100644
--- a/internal/vfs/vfsmock/wrapper.go
+++ b/internal/vfs/vfsmock/wrapper.go
@@ -11,6 +11,7 @@ func Wrap(fs vfs.FS) *FSMock {
ReadFileFunc: fs.ReadFile,
RealpathFunc: fs.Realpath,
RemoveFunc: fs.Remove,
+ ChtimesFunc: fs.Chtimes,
StatFunc: fs.Stat,
UseCaseSensitiveFileNamesFunc: fs.UseCaseSensitiveFileNames,
WalkDirFunc: fs.WalkDir,
diff --git a/internal/vfs/vfstest/vfstest.go b/internal/vfs/vfstest/vfstest.go
index e051b0c347..4e8a0d7fe1 100644
--- a/internal/vfs/vfstest/vfstest.go
+++ b/internal/vfs/vfstest/vfstest.go
@@ -537,6 +537,20 @@ func (m *MapFS) Remove(path string) error {
return m.remove(path)
}
+func (m *MapFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ canonical := m.getCanonicalPath(path)
+ canonicalString := string(canonical)
+ fileInfo := m.m[canonicalString]
+ if fileInfo == nil {
+ // file does not exist
+ return fs.ErrNotExist
+ }
+ fileInfo.ModTime = mTime
+ return nil
+}
+
func (m *MapFS) GetTargetOfSymlink(path string) (string, bool) {
path, _ = strings.CutPrefix(path, "/")
m.mu.RLock()
diff --git a/testdata/baselines/reference/submodule/compiler/libReplacement(libreplacement=true).trace.json b/testdata/baselines/reference/submodule/compiler/libReplacement(libreplacement=true).trace.json
new file mode 100644
index 0000000000..9f241813e7
--- /dev/null
+++ b/testdata/baselines/reference/submodule/compiler/libReplacement(libreplacement=true).trace.json
@@ -0,0 +1,1326 @@
+======== Resolving module '@typescript/lib-decorators' from '/.src/__lib_node_modules_lookup_lib.decorators.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist.
+File '/package.json' does not exist.
+Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators' was not resolved. ========
+======== Resolving module '@typescript/lib-decorators/legacy' from '/.src/__lib_node_modules_lookup_lib.decorators.legacy.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators/legacy' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/collection' from '/.src/__lib_node_modules_lookup_lib.es2015.collection.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/collection' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/collection'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/collection'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/collection' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/core' from '/.src/__lib_node_modules_lookup_lib.es2015.core.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/core' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/core'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/core'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/core' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015' from '/.src/__lib_node_modules_lookup_lib.es2015.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/generator' from '/.src/__lib_node_modules_lookup_lib.es2015.generator.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/generator' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/generator'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/generator'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/generator' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/iterable' from '/.src/__lib_node_modules_lookup_lib.es2015.iterable.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/iterable' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/iterable'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/iterable'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/iterable' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/promise' from '/.src/__lib_node_modules_lookup_lib.es2015.promise.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/promise' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/promise'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/promise'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/promise' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/proxy' from '/.src/__lib_node_modules_lookup_lib.es2015.proxy.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/proxy' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/proxy'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/proxy'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/proxy' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/reflect' from '/.src/__lib_node_modules_lookup_lib.es2015.reflect.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/reflect' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/reflect'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/reflect'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/reflect' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/symbol' from '/.src/__lib_node_modules_lookup_lib.es2015.symbol.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/symbol' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/symbol'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/symbol'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/symbol' was not resolved. ========
+======== Resolving module '@typescript/lib-es2015/symbol-wellknown' from '/.src/__lib_node_modules_lookup_lib.es2015.symbol.wellknown.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2015/symbol-wellknown' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/symbol-wellknown'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2015/symbol-wellknown'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2015/symbol-wellknown' was not resolved. ========
+======== Resolving module '@typescript/lib-es2016/array-include' from '/.src/__lib_node_modules_lookup_lib.es2016.array.include.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2016/array-include' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2016/array-include'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2016/array-include'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2016/array-include' was not resolved. ========
+======== Resolving module '@typescript/lib-es2016' from '/.src/__lib_node_modules_lookup_lib.es2016.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2016' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2016'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2016'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2016' was not resolved. ========
+======== Resolving module '@typescript/lib-es2016/intl' from '/.src/__lib_node_modules_lookup_lib.es2016.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2016/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2016/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2016/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2016/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017/arraybuffer' from '/.src/__lib_node_modules_lookup_lib.es2017.arraybuffer.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017/arraybuffer' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/arraybuffer'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/arraybuffer'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017/arraybuffer' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017' from '/.src/__lib_node_modules_lookup_lib.es2017.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017/date' from '/.src/__lib_node_modules_lookup_lib.es2017.date.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017/date' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/date'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/date'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017/date' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017/intl' from '/.src/__lib_node_modules_lookup_lib.es2017.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017/object' from '/.src/__lib_node_modules_lookup_lib.es2017.object.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017/object' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/object'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/object'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017/object' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017/sharedmemory' from '/.src/__lib_node_modules_lookup_lib.es2017.sharedmemory.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017/sharedmemory' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/sharedmemory'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/sharedmemory'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017/sharedmemory' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017/string' from '/.src/__lib_node_modules_lookup_lib.es2017.string.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017/string' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/string'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/string'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017/string' was not resolved. ========
+======== Resolving module '@typescript/lib-es2017/typedarrays' from '/.src/__lib_node_modules_lookup_lib.es2017.typedarrays.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2017/typedarrays' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/typedarrays'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2017/typedarrays'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2017/typedarrays' was not resolved. ========
+======== Resolving module '@typescript/lib-es2018/asyncgenerator' from '/.src/__lib_node_modules_lookup_lib.es2018.asyncgenerator.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2018/asyncgenerator' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/asyncgenerator'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/asyncgenerator'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2018/asyncgenerator' was not resolved. ========
+======== Resolving module '@typescript/lib-es2018/asynciterable' from '/.src/__lib_node_modules_lookup_lib.es2018.asynciterable.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2018/asynciterable' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/asynciterable'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/asynciterable'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2018/asynciterable' was not resolved. ========
+======== Resolving module '@typescript/lib-es2018' from '/.src/__lib_node_modules_lookup_lib.es2018.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2018' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2018' was not resolved. ========
+======== Resolving module '@typescript/lib-es2018/intl' from '/.src/__lib_node_modules_lookup_lib.es2018.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2018/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2018/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2018/promise' from '/.src/__lib_node_modules_lookup_lib.es2018.promise.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2018/promise' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/promise'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/promise'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2018/promise' was not resolved. ========
+======== Resolving module '@typescript/lib-es2018/regexp' from '/.src/__lib_node_modules_lookup_lib.es2018.regexp.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2018/regexp' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/regexp'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2018/regexp'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2018/regexp' was not resolved. ========
+======== Resolving module '@typescript/lib-es2019/array' from '/.src/__lib_node_modules_lookup_lib.es2019.array.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2019/array' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/array'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/array'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2019/array' was not resolved. ========
+======== Resolving module '@typescript/lib-es2019' from '/.src/__lib_node_modules_lookup_lib.es2019.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2019' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2019' was not resolved. ========
+======== Resolving module '@typescript/lib-es2019/intl' from '/.src/__lib_node_modules_lookup_lib.es2019.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2019/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2019/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2019/object' from '/.src/__lib_node_modules_lookup_lib.es2019.object.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2019/object' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/object'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/object'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2019/object' was not resolved. ========
+======== Resolving module '@typescript/lib-es2019/string' from '/.src/__lib_node_modules_lookup_lib.es2019.string.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2019/string' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/string'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/string'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2019/string' was not resolved. ========
+======== Resolving module '@typescript/lib-es2019/symbol' from '/.src/__lib_node_modules_lookup_lib.es2019.symbol.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2019/symbol' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/symbol'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2019/symbol'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2019/symbol' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/bigint' from '/.src/__lib_node_modules_lookup_lib.es2020.bigint.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/bigint' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/bigint'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/bigint'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/bigint' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020' from '/.src/__lib_node_modules_lookup_lib.es2020.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/date' from '/.src/__lib_node_modules_lookup_lib.es2020.date.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/date' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/date'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/date'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/date' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/intl' from '/.src/__lib_node_modules_lookup_lib.es2020.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/number' from '/.src/__lib_node_modules_lookup_lib.es2020.number.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/number' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/number'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/number'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/number' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/promise' from '/.src/__lib_node_modules_lookup_lib.es2020.promise.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/promise' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/promise'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/promise'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/promise' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/sharedmemory' from '/.src/__lib_node_modules_lookup_lib.es2020.sharedmemory.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/sharedmemory' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/sharedmemory'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/sharedmemory'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/sharedmemory' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/string' from '/.src/__lib_node_modules_lookup_lib.es2020.string.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/string' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/string'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/string'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/string' was not resolved. ========
+======== Resolving module '@typescript/lib-es2020/symbol-wellknown' from '/.src/__lib_node_modules_lookup_lib.es2020.symbol.wellknown.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2020/symbol-wellknown' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/symbol-wellknown'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2020/symbol-wellknown'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2020/symbol-wellknown' was not resolved. ========
+======== Resolving module '@typescript/lib-es2021' from '/.src/__lib_node_modules_lookup_lib.es2021.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2021' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2021' was not resolved. ========
+======== Resolving module '@typescript/lib-es2021/intl' from '/.src/__lib_node_modules_lookup_lib.es2021.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2021/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2021/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2021/promise' from '/.src/__lib_node_modules_lookup_lib.es2021.promise.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2021/promise' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/promise'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/promise'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2021/promise' was not resolved. ========
+======== Resolving module '@typescript/lib-es2021/string' from '/.src/__lib_node_modules_lookup_lib.es2021.string.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2021/string' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/string'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/string'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2021/string' was not resolved. ========
+======== Resolving module '@typescript/lib-es2021/weakref' from '/.src/__lib_node_modules_lookup_lib.es2021.weakref.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2021/weakref' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/weakref'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2021/weakref'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2021/weakref' was not resolved. ========
+======== Resolving module '@typescript/lib-es2022/array' from '/.src/__lib_node_modules_lookup_lib.es2022.array.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2022/array' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/array'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/array'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2022/array' was not resolved. ========
+======== Resolving module '@typescript/lib-es2022' from '/.src/__lib_node_modules_lookup_lib.es2022.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2022' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2022' was not resolved. ========
+======== Resolving module '@typescript/lib-es2022/error' from '/.src/__lib_node_modules_lookup_lib.es2022.error.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2022/error' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/error'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/error'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2022/error' was not resolved. ========
+======== Resolving module '@typescript/lib-es2022/intl' from '/.src/__lib_node_modules_lookup_lib.es2022.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2022/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2022/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2022/object' from '/.src/__lib_node_modules_lookup_lib.es2022.object.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2022/object' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/object'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/object'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2022/object' was not resolved. ========
+======== Resolving module '@typescript/lib-es2022/regexp' from '/.src/__lib_node_modules_lookup_lib.es2022.regexp.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2022/regexp' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/regexp'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/regexp'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2022/regexp' was not resolved. ========
+======== Resolving module '@typescript/lib-es2022/string' from '/.src/__lib_node_modules_lookup_lib.es2022.string.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2022/string' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/string'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2022/string'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2022/string' was not resolved. ========
+======== Resolving module '@typescript/lib-es2023/array' from '/.src/__lib_node_modules_lookup_lib.es2023.array.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2023/array' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023/array'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023/array'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2023/array' was not resolved. ========
+======== Resolving module '@typescript/lib-es2023/collection' from '/.src/__lib_node_modules_lookup_lib.es2023.collection.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2023/collection' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023/collection'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023/collection'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2023/collection' was not resolved. ========
+======== Resolving module '@typescript/lib-es2023' from '/.src/__lib_node_modules_lookup_lib.es2023.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2023' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2023' was not resolved. ========
+======== Resolving module '@typescript/lib-es2023/intl' from '/.src/__lib_node_modules_lookup_lib.es2023.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2023/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2023/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2023/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024/arraybuffer' from '/.src/__lib_node_modules_lookup_lib.es2024.arraybuffer.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024/arraybuffer' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/arraybuffer'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/arraybuffer'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024/arraybuffer' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024/collection' from '/.src/__lib_node_modules_lookup_lib.es2024.collection.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024/collection' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/collection'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/collection'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024/collection' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024' from '/.src/__lib_node_modules_lookup_lib.es2024.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024/object' from '/.src/__lib_node_modules_lookup_lib.es2024.object.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024/object' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/object'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/object'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024/object' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024/promise' from '/.src/__lib_node_modules_lookup_lib.es2024.promise.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024/promise' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/promise'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/promise'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024/promise' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024/regexp' from '/.src/__lib_node_modules_lookup_lib.es2024.regexp.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024/regexp' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/regexp'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/regexp'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024/regexp' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024/sharedmemory' from '/.src/__lib_node_modules_lookup_lib.es2024.sharedmemory.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024/sharedmemory' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/sharedmemory'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/sharedmemory'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024/sharedmemory' was not resolved. ========
+======== Resolving module '@typescript/lib-es2024/string' from '/.src/__lib_node_modules_lookup_lib.es2024.string.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es2024/string' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/string'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es2024/string'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es2024/string' was not resolved. ========
+======== Resolving module '@typescript/lib-es5' from '/.src/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es5' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/array' from '/.src/__lib_node_modules_lookup_lib.esnext.array.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/array' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/array'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/array'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/array' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/collection'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/collection'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/collection' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext' from '/.src/__lib_node_modules_lookup_lib.esnext.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/decorators' from '/.src/__lib_node_modules_lookup_lib.esnext.decorators.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/decorators' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/decorators'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/decorators'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/decorators' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/disposable' from '/.src/__lib_node_modules_lookup_lib.esnext.disposable.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/disposable' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/disposable'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/disposable'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/disposable' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/float16' from '/.src/__lib_node_modules_lookup_lib.esnext.float16.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/float16' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/float16'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/float16'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/float16' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/intl' from '/.src/__lib_node_modules_lookup_lib.esnext.intl.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/intl' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/intl'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/intl'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/intl' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/iterator' from '/.src/__lib_node_modules_lookup_lib.esnext.iterator.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/iterator' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/iterator'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/iterator'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/iterator' was not resolved. ========
+======== Resolving module '@typescript/lib-esnext/promise' from '/.src/__lib_node_modules_lookup_lib.esnext.promise.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-esnext/promise' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/promise'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-esnext/promise'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-esnext/promise' was not resolved. ========
diff --git a/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimple.trace.json b/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimple.trace.json
index c525870d16..840ce3feab 100644
--- a/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimple.trace.json
+++ b/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimple.trace.json
@@ -1,8 +1,43 @@
-======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+======== Resolving module '@typescript/lib-decorators' from '/.src/__lib_node_modules_lookup_lib.decorators.d.ts__.ts'. ========
Module resolution kind is not specified, using 'Bundler'.
Resolving in CJS mode with conditions 'require', 'types'.
File '/.src/package.json' does not exist.
File '/package.json' does not exist.
+Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+File '/node_modules/@typescript/lib-decorators.ts' does not exist.
+File '/node_modules/@typescript/lib-decorators.tsx' does not exist.
+File '/node_modules/@typescript/lib-decorators.d.ts' does not exist.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+File '/node_modules/@typescript/lib-decorators.js' does not exist.
+File '/node_modules/@typescript/lib-decorators.jsx' does not exist.
+======== Module name '@typescript/lib-decorators' was not resolved. ========
+======== Resolving module '@typescript/lib-decorators/legacy' from '/.src/__lib_node_modules_lookup_lib.decorators.legacy.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators/legacy' was not resolved. ========
+======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/.src/node_modules' does not exist, skipping all lookups in it.
@@ -17,3 +52,58 @@ File '/node_modules/@typescript/lib-dom/index.tsx' does not exist.
File '/node_modules/@typescript/lib-dom/index.d.ts' exists - use it as a name resolution result.
Resolving real path for '/node_modules/@typescript/lib-dom/index.d.ts', result '/node_modules/@typescript/lib-dom/index.d.ts'.
======== Module name '@typescript/lib-dom' was successfully resolved to '/node_modules/@typescript/lib-dom/index.d.ts'. ========
+======== Resolving module '@typescript/lib-es5' from '/.src/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+File '/node_modules/@typescript/lib-es5.ts' does not exist.
+File '/node_modules/@typescript/lib-es5.tsx' does not exist.
+File '/node_modules/@typescript/lib-es5.d.ts' does not exist.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+File '/node_modules/@typescript/lib-es5.js' does not exist.
+File '/node_modules/@typescript/lib-es5.jsx' does not exist.
+======== Module name '@typescript/lib-es5' was not resolved. ========
+======== Resolving module '@typescript/lib-scripthost' from '/.src/__lib_node_modules_lookup_lib.scripthost.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+File '/node_modules/@typescript/lib-scripthost.ts' does not exist.
+File '/node_modules/@typescript/lib-scripthost.tsx' does not exist.
+File '/node_modules/@typescript/lib-scripthost.d.ts' does not exist.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+File '/node_modules/@typescript/lib-scripthost.js' does not exist.
+File '/node_modules/@typescript/lib-scripthost.jsx' does not exist.
+======== Module name '@typescript/lib-scripthost' was not resolved. ========
+======== Resolving module '@typescript/lib-webworker/importscripts' from '/.src/__lib_node_modules_lookup_lib.webworker.importscripts.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-webworker/importscripts' was not resolved. ========
diff --git a/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimpleConfig.trace.json b/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimpleConfig.trace.json
index 5b583846ff..3270dfed41 100644
--- a/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimpleConfig.trace.json
+++ b/testdata/baselines/reference/submodule/compiler/libTypeScriptOverrideSimpleConfig.trace.json
@@ -1,8 +1,43 @@
-======== Resolving module '@typescript/lib-dom' from '/somepath/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+======== Resolving module '@typescript/lib-decorators' from '/somepath/__lib_node_modules_lookup_lib.decorators.d.ts__.ts'. ========
Module resolution kind is not specified, using 'Bundler'.
Resolving in CJS mode with conditions 'require', 'types'.
File '/somepath/package.json' does not exist.
File '/package.json' does not exist.
+Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+File '/somepath/node_modules/@typescript/lib-decorators.ts' does not exist.
+File '/somepath/node_modules/@typescript/lib-decorators.tsx' does not exist.
+File '/somepath/node_modules/@typescript/lib-decorators.d.ts' does not exist.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+File '/somepath/node_modules/@typescript/lib-decorators.js' does not exist.
+File '/somepath/node_modules/@typescript/lib-decorators.jsx' does not exist.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators' was not resolved. ========
+======== Resolving module '@typescript/lib-decorators/legacy' from '/somepath/__lib_node_modules_lookup_lib.decorators.legacy.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators/legacy' was not resolved. ========
+======== Resolving module '@typescript/lib-dom' from '/somepath/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
File '/somepath/node_modules/@typescript/lib-dom/package.json' does not exist.
@@ -14,3 +49,58 @@ File '/somepath/node_modules/@typescript/lib-dom/index.tsx' does not exist.
File '/somepath/node_modules/@typescript/lib-dom/index.d.ts' exists - use it as a name resolution result.
Resolving real path for '/somepath/node_modules/@typescript/lib-dom/index.d.ts', result '/somepath/node_modules/@typescript/lib-dom/index.d.ts'.
======== Module name '@typescript/lib-dom' was successfully resolved to '/somepath/node_modules/@typescript/lib-dom/index.d.ts'. ========
+======== Resolving module '@typescript/lib-es5' from '/somepath/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+File '/somepath/node_modules/@typescript/lib-es5.ts' does not exist.
+File '/somepath/node_modules/@typescript/lib-es5.tsx' does not exist.
+File '/somepath/node_modules/@typescript/lib-es5.d.ts' does not exist.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+File '/somepath/node_modules/@typescript/lib-es5.js' does not exist.
+File '/somepath/node_modules/@typescript/lib-es5.jsx' does not exist.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es5' was not resolved. ========
+======== Resolving module '@typescript/lib-scripthost' from '/somepath/__lib_node_modules_lookup_lib.scripthost.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+File '/somepath/node_modules/@typescript/lib-scripthost.ts' does not exist.
+File '/somepath/node_modules/@typescript/lib-scripthost.tsx' does not exist.
+File '/somepath/node_modules/@typescript/lib-scripthost.d.ts' does not exist.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+File '/somepath/node_modules/@typescript/lib-scripthost.js' does not exist.
+File '/somepath/node_modules/@typescript/lib-scripthost.jsx' does not exist.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-scripthost' was not resolved. ========
+======== Resolving module '@typescript/lib-webworker/importscripts' from '/somepath/__lib_node_modules_lookup_lib.webworker.importscripts.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-webworker/importscripts' was not resolved. ========
diff --git a/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolving.trace.json b/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolving.trace.json
index 3fcfca153f..18f21cbca3 100644
--- a/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolving.trace.json
+++ b/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolving.trace.json
@@ -1,8 +1,43 @@
-======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+======== Resolving module '@typescript/lib-decorators' from '/.src/__lib_node_modules_lookup_lib.decorators.d.ts__.ts'. ========
Module resolution kind is not specified, using 'Bundler'.
Resolving in CJS mode with conditions 'require', 'types'.
File '/.src/package.json' does not exist.
File '/package.json' does not exist.
+Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+File '/node_modules/@typescript/lib-decorators.ts' does not exist.
+File '/node_modules/@typescript/lib-decorators.tsx' does not exist.
+File '/node_modules/@typescript/lib-decorators.d.ts' does not exist.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+File '/node_modules/@typescript/lib-decorators.js' does not exist.
+File '/node_modules/@typescript/lib-decorators.jsx' does not exist.
+======== Module name '@typescript/lib-decorators' was not resolved. ========
+======== Resolving module '@typescript/lib-decorators/legacy' from '/.src/__lib_node_modules_lookup_lib.decorators.legacy.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators/legacy' was not resolved. ========
+======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/.src/node_modules' does not exist, skipping all lookups in it.
@@ -33,3 +68,58 @@ File '/node_modules/@typescript/lib-dom/iterable.tsx' does not exist.
File '/node_modules/@typescript/lib-dom/iterable.d.ts' exists - use it as a name resolution result.
Resolving real path for '/node_modules/@typescript/lib-dom/iterable.d.ts', result '/node_modules/@typescript/lib-dom/iterable.d.ts'.
======== Module name '@typescript/lib-dom/iterable' was successfully resolved to '/node_modules/@typescript/lib-dom/iterable.d.ts'. ========
+======== Resolving module '@typescript/lib-es5' from '/.src/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+File '/node_modules/@typescript/lib-es5.ts' does not exist.
+File '/node_modules/@typescript/lib-es5.tsx' does not exist.
+File '/node_modules/@typescript/lib-es5.d.ts' does not exist.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+File '/node_modules/@typescript/lib-es5.js' does not exist.
+File '/node_modules/@typescript/lib-es5.jsx' does not exist.
+======== Module name '@typescript/lib-es5' was not resolved. ========
+======== Resolving module '@typescript/lib-scripthost' from '/.src/__lib_node_modules_lookup_lib.scripthost.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+File '/node_modules/@typescript/lib-scripthost.ts' does not exist.
+File '/node_modules/@typescript/lib-scripthost.tsx' does not exist.
+File '/node_modules/@typescript/lib-scripthost.d.ts' does not exist.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+File '/node_modules/@typescript/lib-scripthost.js' does not exist.
+File '/node_modules/@typescript/lib-scripthost.jsx' does not exist.
+======== Module name '@typescript/lib-scripthost' was not resolved. ========
+======== Resolving module '@typescript/lib-webworker/importscripts' from '/.src/__lib_node_modules_lookup_lib.webworker.importscripts.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/.src/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/.src/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-webworker/importscripts' was not resolved. ========
diff --git a/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolvingConfig.trace.json b/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolvingConfig.trace.json
index 8f2398edd9..7c699fb67f 100644
--- a/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolvingConfig.trace.json
+++ b/testdata/baselines/reference/submodule/compiler/libTypeScriptSubfileResolvingConfig.trace.json
@@ -1,8 +1,43 @@
-======== Resolving module '@typescript/lib-dom' from '/somepath/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+======== Resolving module '@typescript/lib-decorators' from '/somepath/__lib_node_modules_lookup_lib.decorators.d.ts__.ts'. ========
Module resolution kind is not specified, using 'Bundler'.
Resolving in CJS mode with conditions 'require', 'types'.
File '/somepath/package.json' does not exist.
File '/package.json' does not exist.
+Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+File '/somepath/node_modules/@typescript/lib-decorators.ts' does not exist.
+File '/somepath/node_modules/@typescript/lib-decorators.tsx' does not exist.
+File '/somepath/node_modules/@typescript/lib-decorators.d.ts' does not exist.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+File '/somepath/node_modules/@typescript/lib-decorators.js' does not exist.
+File '/somepath/node_modules/@typescript/lib-decorators.jsx' does not exist.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators' was not resolved. ========
+======== Resolving module '@typescript/lib-decorators/legacy' from '/somepath/__lib_node_modules_lookup_lib.decorators.legacy.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-decorators/legacy'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-decorators/legacy' was not resolved. ========
+======== Resolving module '@typescript/lib-dom' from '/somepath/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
File '/somepath/node_modules/@typescript/lib-dom/package.json' does not exist.
@@ -27,3 +62,58 @@ File '/somepath/node_modules/@typescript/lib-dom/iterable.tsx' does not exist.
File '/somepath/node_modules/@typescript/lib-dom/iterable.d.ts' exists - use it as a name resolution result.
Resolving real path for '/somepath/node_modules/@typescript/lib-dom/iterable.d.ts', result '/somepath/node_modules/@typescript/lib-dom/iterable.d.ts'.
======== Module name '@typescript/lib-dom/iterable' was successfully resolved to '/somepath/node_modules/@typescript/lib-dom/iterable.d.ts'. ========
+======== Resolving module '@typescript/lib-es5' from '/somepath/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+File '/somepath/node_modules/@typescript/lib-es5.ts' does not exist.
+File '/somepath/node_modules/@typescript/lib-es5.tsx' does not exist.
+File '/somepath/node_modules/@typescript/lib-es5.d.ts' does not exist.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-es5'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+File '/somepath/node_modules/@typescript/lib-es5.js' does not exist.
+File '/somepath/node_modules/@typescript/lib-es5.jsx' does not exist.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-es5' was not resolved. ========
+======== Resolving module '@typescript/lib-scripthost' from '/somepath/__lib_node_modules_lookup_lib.scripthost.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+File '/somepath/node_modules/@typescript/lib-scripthost.ts' does not exist.
+File '/somepath/node_modules/@typescript/lib-scripthost.tsx' does not exist.
+File '/somepath/node_modules/@typescript/lib-scripthost.d.ts' does not exist.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-scripthost'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+File '/somepath/node_modules/@typescript/lib-scripthost.js' does not exist.
+File '/somepath/node_modules/@typescript/lib-scripthost.jsx' does not exist.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-scripthost' was not resolved. ========
+======== Resolving module '@typescript/lib-webworker/importscripts' from '/somepath/__lib_node_modules_lookup_lib.webworker.importscripts.d.ts__.ts'. ========
+Module resolution kind is not specified, using 'Bundler'.
+Resolving in CJS mode with conditions 'require', 'types'.
+File '/somepath/package.json' does not exist according to earlier cached lookups.
+File '/package.json' does not exist according to earlier cached lookups.
+Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
+Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
+Directory '/somepath/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Directory '/node_modules' does not exist, skipping all lookups in it.
+Directory '/node_modules/@types' does not exist, skipping all lookups in it.
+Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
+Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
+Directory '/node_modules' does not exist, skipping all lookups in it.
+======== Module name '@typescript/lib-webworker/importscripts' was not resolved. ========
diff --git a/testdata/baselines/reference/tsbuild/clean/file-name-and-output-name-clashing.js b/testdata/baselines/reference/tsbuild/clean/file-name-and-output-name-clashing.js
new file mode 100644
index 0000000000..1d6c33937a
--- /dev/null
+++ b/testdata/baselines/reference/tsbuild/clean/file-name-and-output-name-clashing.js
@@ -0,0 +1,16 @@
+currentDirectory::/home/src/workspaces/solution
+useCaseSensitiveFileNames::true
+Input::
+//// [/home/src/workspaces/solution/bar.ts] *new*
+
+//// [/home/src/workspaces/solution/index.js] *new*
+
+//// [/home/src/workspaces/solution/tsconfig.json] *new*
+{
+ "compilerOptions": { "allowJs": true }
+}
+
+tsgo --b --clean
+ExitStatus:: Success
+Output::
+
diff --git a/testdata/baselines/reference/tsbuild/clean/tsx-with-dts-emit.js b/testdata/baselines/reference/tsbuild/clean/tsx-with-dts-emit.js
new file mode 100644
index 0000000000..cb0a1849c9
--- /dev/null
+++ b/testdata/baselines/reference/tsbuild/clean/tsx-with-dts-emit.js
@@ -0,0 +1,103 @@
+currentDirectory::/home/src/workspaces/solution
+useCaseSensitiveFileNames::true
+Input::
+//// [/home/src/workspaces/solution/project/src/main.tsx] *new*
+export const x = 10;
+//// [/home/src/workspaces/solution/project/tsconfig.json] *new*
+{
+ "compilerOptions": { "declaration": true },
+ "include": ["src/**/*.tsx", "src/**/*.ts"]
+}
+
+tsgo --b project -v --explainFiles
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * project/tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'project/tsconfig.json' is out of date because output file 'project/tsconfig.tsbuildinfo' does not exist
+
+[[90mHH:MM:SS AM[0m] Building project 'project/tsconfig.json'...
+
+../../tslibs/TS/Lib/lib.d.ts
+ Default library for target 'ES5'
+project/src/main.tsx
+ Matched by include pattern 'src/**/*.tsx' in 'project/tsconfig.json'
+//// [/home/src/tslibs/TS/Lib/lib.d.ts] *Lib*
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+interface ReadonlyArray {}
+interface SymbolConstructor {
+ (desc?: string | number): symbol;
+ for(name: string): symbol;
+ readonly toStringTag: symbol;
+}
+declare var Symbol: SymbolConstructor;
+interface Symbol {
+ readonly [Symbol.toStringTag]: string;
+}
+declare const console: { log(msg: any): void; };
+//// [/home/src/workspaces/solution/project/src/main.d.ts] *new*
+export declare const x = 10;
+
+//// [/home/src/workspaces/solution/project/src/main.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.x = void 0;
+exports.x = 10;
+
+//// [/home/src/workspaces/solution/project/tsconfig.tsbuildinfo] *new*
+{"version":"FakeTSVersion","root":["./src/main.tsx"]}
+//// [/home/src/workspaces/solution/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./src/main.tsx"
+ ],
+ "original": "./src/main.tsx"
+ }
+ ],
+ "size": 53
+}
+
+project/tsconfig.json::
+SemanticDiagnostics::
+*refresh* /home/src/tslibs/TS/Lib/lib.d.ts
+*refresh* /home/src/workspaces/solution/project/src/main.tsx
+Signatures::
+(stored at emit) /home/src/workspaces/solution/project/src/main.tsx
+
+
+Edit [0]:: no change
+
+tsgo --b project -v --explainFiles
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * project/tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'project/tsconfig.json' is up to date because newest input 'project/src/main.tsx' is older than output 'project/src/main.js'
+
+
+
+
+Edit [1]:: clean build
+
+tsgo -b project --clean
+ExitStatus:: Success
+Output::
+//// [/home/src/workspaces/solution/project/src/main.d.ts] *deleted*
+//// [/home/src/workspaces/solution/project/src/main.js] *deleted*
+//// [/home/src/workspaces/solution/project/tsconfig.tsbuildinfo] *deleted*
+
diff --git a/testdata/baselines/reference/tsbuild/commandLine/different-options-with-incremental.js b/testdata/baselines/reference/tsbuild/commandLine/different-options-with-incremental.js
new file mode 100644
index 0000000000..7172bf4267
--- /dev/null
+++ b/testdata/baselines/reference/tsbuild/commandLine/different-options-with-incremental.js
@@ -0,0 +1,1609 @@
+currentDirectory::/home/src/workspaces/project
+useCaseSensitiveFileNames::true
+Input::
+//// [/home/src/workspaces/project/a.ts] *new*
+export const a = 10;const aLocal = 10;
+//// [/home/src/workspaces/project/b.ts] *new*
+export const b = 10;const bLocal = 10;
+//// [/home/src/workspaces/project/c.ts] *new*
+import { a } from "./a";export const c = a;
+//// [/home/src/workspaces/project/d.ts] *new*
+import { b } from "./b";export const d = b;
+//// [/home/src/workspaces/project/tsconfig.json] *new*
+{
+ "compilerOptions": {
+ "incremental": true
+ }
+}
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/tslibs/TS/Lib/lib.d.ts] *Lib*
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+interface ReadonlyArray {}
+interface SymbolConstructor {
+ (desc?: string | number): symbol;
+ for(name: string): symbol;
+ readonly toStringTag: symbol;
+}
+declare var Symbol: SymbolConstructor;
+interface Symbol {
+ readonly [Symbol.toStringTag]: string;
+}
+declare const console: { log(msg: any): void; };
+//// [/home/src/workspaces/project/a.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 10;
+
+//// [/home/src/workspaces/project/b.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+
+//// [/home/src/workspaces/project/c.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+
+//// [/home/src/workspaces/project/d.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *new*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;"],"fileIdsList":[[2],[3]],"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "impliedNodeFormat": "CommonJS"
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1251
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+*refresh* /home/src/tslibs/TS/Lib/lib.d.ts
+*refresh* /home/src/workspaces/project/a.ts
+*refresh* /home/src/workspaces/project/b.ts
+*refresh* /home/src/workspaces/project/c.ts
+*refresh* /home/src/workspaces/project/d.ts
+Signatures::
+
+
+Edit [0]:: with sourceMap
+
+tsgo --build --verbose --sourceMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 10;
+//# sourceMappingURL=a.js.map
+//// [/home/src/workspaces/project/a.js.map] *new*
+{"version":3,"file":"a.js","sourceRoot":"","sources":["a.ts"],"names":[],"mappings":";;;AAAa,QAAA,CAAC,GAAG,EAAE,CAAC;AAAA,MAAM,MAAM,GAAG,EAAE,CAAC"}
+//// [/home/src/workspaces/project/b.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+//# sourceMappingURL=b.js.map
+//// [/home/src/workspaces/project/b.js.map] *new*
+{"version":3,"file":"b.js","sourceRoot":"","sources":["b.ts"],"names":[],"mappings":";;;AAAa,QAAA,CAAC,GAAG,EAAE,CAAC;AAAA,MAAM,MAAM,GAAG,EAAE,CAAC"}
+//// [/home/src/workspaces/project/c.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+//# sourceMappingURL=c.js.map
+//// [/home/src/workspaces/project/c.js.map] *new*
+{"version":3,"file":"c.js","sourceRoot":"","sources":["c.ts"],"names":[],"mappings":";;;AAAA,2BAAwB;AAAa,QAAA,CAAC,GAAG,KAAC,CAAC"}
+//// [/home/src/workspaces/project/d.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+//# sourceMappingURL=d.js.map
+//// [/home/src/workspaces/project/d.js.map] *new*
+{"version":3,"file":"d.js","sourceRoot":"","sources":["d.ts"],"names":[],"mappings":";;;AAAA,2BAAwB;AAAa,QAAA,CAAC,GAAG,KAAC,CAAC"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;"],"fileIdsList":[[2],[3]],"options":{"sourceMap":true},"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "impliedNodeFormat": "CommonJS"
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "sourceMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1280
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [1]:: should re-emit only js so they dont contain sourcemap
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 10;
+
+//// [/home/src/workspaces/project/b.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+
+//// [/home/src/workspaces/project/c.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+
+//// [/home/src/workspaces/project/d.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;"],"fileIdsList":[[2],[3]],"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "impliedNodeFormat": "CommonJS"
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "impliedNodeFormat": "CommonJS"
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1251
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [2]:: with declaration, emit Dts and should not emit js
+
+tsgo --build --verbose --declaration
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.d.ts] *new*
+export declare const a = 10;
+
+//// [/home/src/workspaces/project/b.d.ts] *new*
+export declare const b = 10;
+
+//// [/home/src/workspaces/project/c.d.ts] *new*
+export declare const c = 10;
+
+//// [/home/src/workspaces/project/d.d.ts] *new*
+export declare const d = 10;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"declaration":true},"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "declaration": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1730
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+(stored at emit) /home/src/workspaces/project/a.ts
+(stored at emit) /home/src/workspaces/project/b.ts
+(stored at emit) /home/src/workspaces/project/c.ts
+(stored at emit) /home/src/workspaces/project/d.ts
+
+
+Edit [3]:: with declaration and declarationMap
+
+tsgo --build --verbose --declaration --declarationMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.d.ts] *modified*
+export declare const a = 10;
+//# sourceMappingURL=a.d.ts.map
+//// [/home/src/workspaces/project/a.d.ts.map] *new*
+{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["a.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,CAAC,KAAK,CAAC"}
+//// [/home/src/workspaces/project/b.d.ts] *modified*
+export declare const b = 10;
+//# sourceMappingURL=b.d.ts.map
+//// [/home/src/workspaces/project/b.d.ts.map] *new*
+{"version":3,"file":"b.d.ts","sourceRoot":"","sources":["b.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,CAAC,KAAK,CAAC"}
+//// [/home/src/workspaces/project/c.d.ts] *modified*
+export declare const c = 10;
+//# sourceMappingURL=c.d.ts.map
+//// [/home/src/workspaces/project/c.d.ts.map] *new*
+{"version":3,"file":"c.d.ts","sourceRoot":"","sources":["c.ts"],"names":[],"mappings":"AAAwB,eAAO,MAAM,CAAC,KAAI,CAAC"}
+//// [/home/src/workspaces/project/d.d.ts] *modified*
+export declare const d = 10;
+//# sourceMappingURL=d.d.ts.map
+//// [/home/src/workspaces/project/d.d.ts.map] *new*
+{"version":3,"file":"d.d.ts","sourceRoot":"","sources":["d.ts"],"names":[],"mappings":"AAAwB,eAAO,MAAM,CAAC,KAAI,CAAC"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"declaration":true,"declarationMap":true},"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "declaration": true,
+ "declarationMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1752
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [4]:: no change
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is up to date because newest input 'd.ts' is older than output 'tsconfig.tsbuildinfo'
+
+
+
+
+Edit [5]:: local change
+//// [/home/src/workspaces/project/a.ts] *modified*
+export const a = 10;const aLocal = 100;
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because output 'tsconfig.tsbuildinfo' is older than input 'a.ts'
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 100;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1700
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+*refresh* /home/src/workspaces/project/a.ts
+Signatures::
+(computed .d.ts) /home/src/workspaces/project/a.ts
+
+
+Edit [6]:: with declaration and declarationMap
+
+tsgo --build --verbose --declaration --declarationMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/a.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/b.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/b.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/c.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/c.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/d.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/d.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"declaration":true,"declarationMap":true},"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "declaration": true,
+ "declarationMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1753
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [7]:: no change
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is up to date because newest input 'a.ts' is older than output 'tsconfig.tsbuildinfo'
+
+
+
+
+Edit [8]:: with inlineSourceMap
+
+tsgo --build --verbose --inlineSourceMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 100;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQWEsUUFBQSxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQUEsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDIn0=
+//// [/home/src/workspaces/project/b.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQWEsUUFBQSxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQUEsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDIn0=
+//// [/home/src/workspaces/project/c.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkJBQXdCO0FBQWEsUUFBQSxDQUFDLEdBQUcsS0FBQyxDQUFDIn0=
+//// [/home/src/workspaces/project/d.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkJBQXdCO0FBQWEsUUFBQSxDQUFDLEdBQUcsS0FBQyxDQUFDIn0=
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"inlineSourceMap":true},"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "inlineSourceMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1735
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [9]:: with sourceMap
+
+tsgo --build --verbose --sourceMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 100;
+//# sourceMappingURL=a.js.map
+//// [/home/src/workspaces/project/a.js.map] *modified*
+{"version":3,"file":"a.js","sourceRoot":"","sources":["a.ts"],"names":[],"mappings":";;;AAAa,QAAA,CAAC,GAAG,EAAE,CAAC;AAAA,MAAM,MAAM,GAAG,GAAG,CAAC"}
+//// [/home/src/workspaces/project/b.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+//# sourceMappingURL=b.js.map
+//// [/home/src/workspaces/project/b.js.map] *rewrite with same content*
+//// [/home/src/workspaces/project/c.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+//# sourceMappingURL=c.js.map
+//// [/home/src/workspaces/project/c.js.map] *rewrite with same content*
+//// [/home/src/workspaces/project/d.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+//# sourceMappingURL=d.js.map
+//// [/home/src/workspaces/project/d.js.map] *rewrite with same content*
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"sourceMap":true},"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "sourceMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1729
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [10]:: emit js files
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 100;
+
+//// [/home/src/workspaces/project/b.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+
+//// [/home/src/workspaces/project/c.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+
+//// [/home/src/workspaces/project/d.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1700
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [11]:: with declaration and declarationMap
+
+tsgo --build --verbose --declaration --declarationMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/a.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/b.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/b.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/c.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/c.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/d.d.ts] *rewrite with same content*
+//// [/home/src/workspaces/project/d.d.ts.map] *rewrite with same content*
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"declaration":true,"declarationMap":true},"referencedMap":[[4,1],[5,2]]}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "c74d6b68e2cb0ed4cb8c18e3879119d9-export const a = 10;const aLocal = 100;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "declaration": true,
+ "declarationMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "size": 1753
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [12]:: with declaration and declarationMap, should not re-emit
+
+tsgo --build --verbose --declaration --declarationMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is up to date because newest input 'a.ts' is older than output 'tsconfig.tsbuildinfo'
+
+
diff --git a/testdata/baselines/reference/tsbuild/commandLine/different-options.js b/testdata/baselines/reference/tsbuild/commandLine/different-options.js
new file mode 100644
index 0000000000..0dead645da
--- /dev/null
+++ b/testdata/baselines/reference/tsbuild/commandLine/different-options.js
@@ -0,0 +1,1316 @@
+currentDirectory::/home/src/workspaces/project
+useCaseSensitiveFileNames::true
+Input::
+//// [/home/src/workspaces/project/a.ts] *new*
+export const a = 10;const aLocal = 10;
+//// [/home/src/workspaces/project/b.ts] *new*
+export const b = 10;const bLocal = 10;
+//// [/home/src/workspaces/project/c.ts] *new*
+import { a } from "./a";export const c = a;
+//// [/home/src/workspaces/project/d.ts] *new*
+import { b } from "./b";export const d = b;
+//// [/home/src/workspaces/project/tsconfig.json] *new*
+{
+ "compilerOptions": {
+ "composite": true
+ }
+}
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/tslibs/TS/Lib/lib.d.ts] *Lib*
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+interface ReadonlyArray {}
+interface SymbolConstructor {
+ (desc?: string | number): symbol;
+ for(name: string): symbol;
+ readonly toStringTag: symbol;
+}
+declare var Symbol: SymbolConstructor;
+interface Symbol {
+ readonly [Symbol.toStringTag]: string;
+}
+declare const console: { log(msg: any): void; };
+//// [/home/src/workspaces/project/a.d.ts] *new*
+export declare const a = 10;
+
+//// [/home/src/workspaces/project/a.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 10;
+
+//// [/home/src/workspaces/project/b.d.ts] *new*
+export declare const b = 10;
+
+//// [/home/src/workspaces/project/b.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+
+//// [/home/src/workspaces/project/c.d.ts] *new*
+export declare const c = 10;
+
+//// [/home/src/workspaces/project/c.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+
+//// [/home/src/workspaces/project/d.d.ts] *new*
+export declare const d = 10;
+
+//// [/home/src/workspaces/project/d.js] *new*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *new*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"composite":true},"referencedMap":[[4,1],[5,2]],"latestChangedDtsFile":"./d.d.ts"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *new*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "composite": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "latestChangedDtsFile": "./d.d.ts",
+ "size": 1762
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+*refresh* /home/src/tslibs/TS/Lib/lib.d.ts
+*refresh* /home/src/workspaces/project/a.ts
+*refresh* /home/src/workspaces/project/b.ts
+*refresh* /home/src/workspaces/project/c.ts
+*refresh* /home/src/workspaces/project/d.ts
+Signatures::
+(stored at emit) /home/src/workspaces/project/a.ts
+(stored at emit) /home/src/workspaces/project/b.ts
+(stored at emit) /home/src/workspaces/project/c.ts
+(stored at emit) /home/src/workspaces/project/d.ts
+
+
+Edit [0]:: with sourceMap
+
+tsgo --build --verbose --sourceMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 10;
+//# sourceMappingURL=a.js.map
+//// [/home/src/workspaces/project/a.js.map] *new*
+{"version":3,"file":"a.js","sourceRoot":"","sources":["a.ts"],"names":[],"mappings":";;;AAAa,QAAA,CAAC,GAAG,EAAE,CAAC;AAAA,MAAM,MAAM,GAAG,EAAE,CAAC"}
+//// [/home/src/workspaces/project/b.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+//# sourceMappingURL=b.js.map
+//// [/home/src/workspaces/project/b.js.map] *new*
+{"version":3,"file":"b.js","sourceRoot":"","sources":["b.ts"],"names":[],"mappings":";;;AAAa,QAAA,CAAC,GAAG,EAAE,CAAC;AAAA,MAAM,MAAM,GAAG,EAAE,CAAC"}
+//// [/home/src/workspaces/project/c.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+//# sourceMappingURL=c.js.map
+//// [/home/src/workspaces/project/c.js.map] *new*
+{"version":3,"file":"c.js","sourceRoot":"","sources":["c.ts"],"names":[],"mappings":";;;AAAA,2BAAwB;AAAa,QAAA,CAAC,GAAG,KAAC,CAAC"}
+//// [/home/src/workspaces/project/d.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+//# sourceMappingURL=d.js.map
+//// [/home/src/workspaces/project/d.js.map] *new*
+{"version":3,"file":"d.js","sourceRoot":"","sources":["d.ts"],"names":[],"mappings":";;;AAAA,2BAAwB;AAAa,QAAA,CAAC,GAAG,KAAC,CAAC"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"composite":true,"sourceMap":true},"referencedMap":[[4,1],[5,2]],"latestChangedDtsFile":"./d.d.ts"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "composite": true,
+ "sourceMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "latestChangedDtsFile": "./d.d.ts",
+ "size": 1779
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [1]:: should re-emit only js so they dont contain sourcemap
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 10;
+
+//// [/home/src/workspaces/project/b.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.b = void 0;
+exports.b = 10;
+const bLocal = 10;
+
+//// [/home/src/workspaces/project/c.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.c = void 0;
+const a_1 = require("./a");
+exports.c = a_1.a;
+
+//// [/home/src/workspaces/project/d.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.d = void 0;
+const b_1 = require("./b");
+exports.d = b_1.b;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"composite":true},"referencedMap":[[4,1],[5,2]],"latestChangedDtsFile":"./d.d.ts"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "composite": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "latestChangedDtsFile": "./d.d.ts",
+ "size": 1762
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [2]:: with declaration should not emit anything
+
+tsgo --build --verbose --declaration
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is up to date because newest input 'd.ts' is older than output 'tsconfig.tsbuildinfo'
+
+
+
+
+Edit [3]:: no change
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is up to date because newest input 'd.ts' is older than output 'tsconfig.tsbuildinfo'
+
+
+
+
+Edit [4]:: with declaration and declarationMap
+
+tsgo --build --verbose --declaration --declarationMap
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.d.ts] *modified*
+export declare const a = 10;
+//# sourceMappingURL=a.d.ts.map
+//// [/home/src/workspaces/project/a.d.ts.map] *new*
+{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["a.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,CAAC,KAAK,CAAC"}
+//// [/home/src/workspaces/project/b.d.ts] *modified*
+export declare const b = 10;
+//# sourceMappingURL=b.d.ts.map
+//// [/home/src/workspaces/project/b.d.ts.map] *new*
+{"version":3,"file":"b.d.ts","sourceRoot":"","sources":["b.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,CAAC,KAAK,CAAC"}
+//// [/home/src/workspaces/project/c.d.ts] *modified*
+export declare const c = 10;
+//# sourceMappingURL=c.d.ts.map
+//// [/home/src/workspaces/project/c.d.ts.map] *new*
+{"version":3,"file":"c.d.ts","sourceRoot":"","sources":["c.ts"],"names":[],"mappings":"AAAwB,eAAO,MAAM,CAAC,KAAI,CAAC"}
+//// [/home/src/workspaces/project/d.d.ts] *modified*
+export declare const d = 10;
+//# sourceMappingURL=d.d.ts.map
+//// [/home/src/workspaces/project/d.d.ts.map] *new*
+{"version":3,"file":"d.d.ts","sourceRoot":"","sources":["d.ts"],"names":[],"mappings":"AAAwB,eAAO,MAAM,CAAC,KAAI,CAAC"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"composite":true,"declaration":true,"declarationMap":true},"referencedMap":[[4,1],[5,2]],"latestChangedDtsFile":"./d.d.ts"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "composite": true,
+ "declaration": true,
+ "declarationMap": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "latestChangedDtsFile": "./d.d.ts",
+ "size": 1803
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [5]:: should re-emit only dts so they dont contain sourcemap
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because buildinfo file 'tsconfig.tsbuildinfo' indicates there is change in compilerOptions
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.d.ts] *modified*
+export declare const a = 10;
+
+//// [/home/src/workspaces/project/b.d.ts] *modified*
+export declare const b = 10;
+
+//// [/home/src/workspaces/project/c.d.ts] *modified*
+export declare const c = 10;
+
+//// [/home/src/workspaces/project/d.d.ts] *modified*
+export declare const d = 10;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true,"impliedNodeFormat":1},{"version":"6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;","signature":"5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n","impliedNodeFormat":1},{"version":"bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;","signature":"eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n","impliedNodeFormat":1},{"version":"28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;","signature":"6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n","impliedNodeFormat":1},{"version":"b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;","signature":"3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n","impliedNodeFormat":1}],"fileIdsList":[[2],[3]],"options":{"composite":true},"referencedMap":[[4,1],[5,2]],"latestChangedDtsFile":"./d.d.ts"}
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo.readable.baseline.txt] *modified*
+{
+ "version": "FakeTSVersion",
+ "root": [
+ {
+ "files": [
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "original": [
+ 2,
+ 5
+ ]
+ }
+ ],
+ "fileNames": [
+ "lib.d.ts",
+ "./a.ts",
+ "./b.ts",
+ "./c.ts",
+ "./d.ts"
+ ],
+ "fileInfos": [
+ {
+ "fileName": "lib.d.ts",
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ninterface SymbolConstructor {\n (desc?: string | number): symbol;\n for(name: string): symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true,
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./a.ts",
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "6f850043fadb2d6b35e16ae1adaad5a5-export const a = 10;const aLocal = 10;",
+ "signature": "5d46ba05302682a2bc47daa29368141f-export declare const a = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./b.ts",
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "bf1b9c3562b043596607d537fbaf9814-export const b = 10;const bLocal = 10;",
+ "signature": "eaed5dafb4668e1b7c86b65b584b776a-export declare const b = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./c.ts",
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "28822e22fad7308e03af07d91b210c8f-import { a } from \"./a\";export const c = a;",
+ "signature": "6bc89426f721fe78f6ac43d3e4d9058f-export declare const c = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ },
+ {
+ "fileName": "./d.ts",
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": "CommonJS",
+ "original": {
+ "version": "b392c90ba2c0413defc12f6bbf323140-import { b } from \"./b\";export const d = b;",
+ "signature": "3624f737ffc30774e872b3f5a7340537-export declare const d = 10;\n",
+ "impliedNodeFormat": 1
+ }
+ }
+ ],
+ "fileIdsList": [
+ [
+ "./a.ts"
+ ],
+ [
+ "./b.ts"
+ ]
+ ],
+ "options": {
+ "composite": true
+ },
+ "referencedMap": {
+ "./c.ts": [
+ "./a.ts"
+ ],
+ "./d.ts": [
+ "./b.ts"
+ ]
+ },
+ "latestChangedDtsFile": "./d.d.ts",
+ "size": 1762
+}
+
+tsconfig.json::
+SemanticDiagnostics::
+Signatures::
+
+
+Edit [6]:: with emitDeclarationOnly should not emit anything
+
+tsgo --build --verbose --emitDeclarationOnly
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is up to date because newest input 'd.ts' is older than output 'tsconfig.tsbuildinfo'
+
+
+
+
+Edit [7]:: no change
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is up to date because newest input 'd.ts' is older than output 'tsconfig.tsbuildinfo'
+
+
+
+
+Edit [8]:: local change
+//// [/home/src/workspaces/project/a.ts] *modified*
+export const a = 10;const aLocal = 100;
+
+tsgo --build --verbose
+ExitStatus:: Success
+Output::
+[[90mHH:MM:SS AM[0m] Projects in this build:
+ * tsconfig.json
+
+[[90mHH:MM:SS AM[0m] Project 'tsconfig.json' is out of date because output 'tsconfig.tsbuildinfo' is older than input 'a.ts'
+
+[[90mHH:MM:SS AM[0m] Building project 'tsconfig.json'...
+
+//// [/home/src/workspaces/project/a.js] *modified*
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.a = void 0;
+exports.a = 10;
+const aLocal = 100;
+
+//// [/home/src/workspaces/project/tsconfig.tsbuildinfo] *modified*
+{"version":"FakeTSVersion","root":[[2,5]],"fileNames":["lib.d.ts","./a.ts","./b.ts","./c.ts","./d.ts"],"fileInfos":[{"version":"8859c12c614ce56ba9a18e58384a198f-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray