Skip to content

Commit 32b6c48

Browse files
Set implied node format during source file creation (#637)
1 parent 7363c09 commit 32b6c48

File tree

191 files changed

+2094
-2377
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

191 files changed

+2094
-2377
lines changed

internal/ast/ast.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -8666,6 +8666,11 @@ type CommentDirective struct {
86668666

86678667
// SourceFile
86688668

8669+
type SourceFileMetaData struct {
8670+
PackageJsonType string
8671+
ImpliedNodeFormat core.ResolutionMode
8672+
}
8673+
86698674
type SourceFile struct {
86708675
NodeBase
86718676
DeclarationBase
@@ -8727,7 +8732,6 @@ type SourceFile struct {
87278732

87288733
// !!!
87298734

8730-
ImpliedNodeFormat core.ModuleKind
87318735
CommonJsModuleIndicator *Node
87328736
ExternalModuleIndicator *Node
87338737
JsGlobalAugmentations SymbolTable
@@ -8812,7 +8816,6 @@ func (node *SourceFile) copyFrom(other *SourceFile) {
88128816
node.ReferencedFiles = other.ReferencedFiles
88138817
node.TypeReferenceDirectives = other.TypeReferenceDirectives
88148818
node.LibReferenceDirectives = other.LibReferenceDirectives
8815-
node.ImpliedNodeFormat = other.ImpliedNodeFormat
88168819
node.CommonJsModuleIndicator = other.CommonJsModuleIndicator
88178820
node.ExternalModuleIndicator = other.ExternalModuleIndicator
88188821
node.JsGlobalAugmentations = other.JsGlobalAugmentations

internal/ast/utilities.go

+24-11
Original file line numberDiff line numberDiff line change
@@ -2357,27 +2357,40 @@ func IsDefaultImport(node *Node /*ImportDeclaration | ImportEqualsDeclaration |
23572357
return importClause != nil && importClause.AsImportClause().name != nil
23582358
}
23592359

2360-
func GetEmitModuleFormatOfFileWorker(sourceFile *SourceFile, options *core.CompilerOptions) core.ModuleKind {
2361-
result := GetImpliedNodeFormatForEmitWorker(sourceFile, options)
2360+
func GetImpliedNodeFormatForFile(path string, packageJsonType string) core.ModuleKind {
2361+
impliedNodeFormat := core.ResolutionModeNone
2362+
if tspath.FileExtensionIsOneOf(path, []string{tspath.ExtensionDmts, tspath.ExtensionMts, tspath.ExtensionMjs}) {
2363+
impliedNodeFormat = core.ResolutionModeESM
2364+
} else if tspath.FileExtensionIsOneOf(path, []string{tspath.ExtensionDcts, tspath.ExtensionCts, tspath.ExtensionCjs}) {
2365+
impliedNodeFormat = core.ResolutionModeCommonJS
2366+
} else if packageJsonType != "" && tspath.FileExtensionIsOneOf(path, []string{tspath.ExtensionDts, tspath.ExtensionTs, tspath.ExtensionTsx, tspath.ExtensionJs, tspath.ExtensionJsx}) {
2367+
impliedNodeFormat = core.IfElse(packageJsonType == "module", core.ResolutionModeESM, core.ResolutionModeCommonJS)
2368+
}
2369+
2370+
return impliedNodeFormat
2371+
}
2372+
2373+
func GetEmitModuleFormatOfFileWorker(sourceFile *SourceFile, options *core.CompilerOptions, sourceFileMetaData *SourceFileMetaData) core.ModuleKind {
2374+
result := GetImpliedNodeFormatForEmitWorker(sourceFile.FileName(), options, sourceFileMetaData)
23622375
if result != core.ModuleKindNone {
23632376
return result
23642377
}
23652378
return options.GetEmitModuleKind()
23662379
}
23672380

2368-
func GetImpliedNodeFormatForEmitWorker(sourceFile *SourceFile, options *core.CompilerOptions) core.ResolutionMode {
2381+
func GetImpliedNodeFormatForEmitWorker(fileName string, options *core.CompilerOptions, sourceFileMetaData *SourceFileMetaData) core.ModuleKind {
23692382
moduleKind := options.GetEmitModuleKind()
2370-
if core.ModuleKindNode16 <= moduleKind && moduleKind <= core.ModuleKindNodeNext {
2371-
return sourceFile.ImpliedNodeFormat
2383+
if core.ModuleKindNode16 <= moduleKind && moduleKind <= core.ModuleKindNodeNext && sourceFileMetaData != nil {
2384+
return sourceFileMetaData.ImpliedNodeFormat
23722385
}
2373-
if sourceFile.ImpliedNodeFormat == core.ModuleKindCommonJS &&
2374-
( /*sourceFile.packageJsonScope.contents.packageJsonContent.type == "commonjs" ||*/ // !!!
2375-
tspath.FileExtensionIsOneOf(sourceFile.FileName(), []string{tspath.ExtensionCjs, tspath.ExtensionCts})) {
2386+
if sourceFileMetaData != nil && sourceFileMetaData.ImpliedNodeFormat == core.ModuleKindCommonJS &&
2387+
(sourceFileMetaData.PackageJsonType != "module" ||
2388+
tspath.FileExtensionIsOneOf(fileName, []string{tspath.ExtensionCjs, tspath.ExtensionCts})) {
23762389
return core.ModuleKindCommonJS
23772390
}
2378-
if sourceFile.ImpliedNodeFormat == core.ModuleKindESNext &&
2379-
( /*sourceFile.packageJsonScope?.contents.packageJsonContent.type === "module" ||*/ // !!!
2380-
tspath.FileExtensionIsOneOf(sourceFile.fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) {
2391+
if sourceFileMetaData != nil && sourceFileMetaData.ImpliedNodeFormat == core.ModuleKindESNext &&
2392+
(sourceFileMetaData.PackageJsonType == "module" ||
2393+
tspath.FileExtensionIsOneOf(fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts})) {
23812394
return core.ModuleKindESNext
23822395
}
23832396
return core.ModuleKindNone

internal/checker/checker.go

+1
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ type Program interface {
515515
GetEmitModuleFormatOfFile(sourceFile *ast.SourceFile) core.ModuleKind
516516
GetImpliedNodeFormatForEmit(sourceFile *ast.SourceFile) core.ModuleKind
517517
GetResolvedModule(currentSourceFile *ast.SourceFile, moduleReference string) *ast.SourceFile
518+
GetSourceFileMetaData(path tspath.Path) *ast.SourceFileMetaData
518519
}
519520

520521
type Host interface{}

internal/checker/grammarchecks.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,8 @@ func (c *Checker) checkGrammarForInOrForOfStatement(forInOrOfStatement *ast.ForI
12171217
}
12181218
switch c.moduleKind {
12191219
case core.ModuleKindNode16, core.ModuleKindNodeNext:
1220-
if sourceFile.ImpliedNodeFormat == core.ModuleKindCommonJS {
1220+
sourceFileMetaData := c.program.GetSourceFileMetaData(sourceFile.Path())
1221+
if sourceFileMetaData != nil && sourceFileMetaData.ImpliedNodeFormat == core.ModuleKindCommonJS {
12211222
c.diagnostics.Add(createDiagnosticForNode(forInOrOfStatement.AwaitModifier, diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level))
12221223
break
12231224
}
@@ -1719,7 +1720,8 @@ func (c *Checker) checkGrammarAwaitOrAwaitUsing(node *ast.Node) bool {
17191720
switch c.moduleKind {
17201721
case core.ModuleKindNode16,
17211722
core.ModuleKindNodeNext:
1722-
if sourceFile.ImpliedNodeFormat == core.ModuleKindCommonJS {
1723+
sourceFileMetaData := c.program.GetSourceFileMetaData(sourceFile.Path())
1724+
if sourceFileMetaData != nil && sourceFileMetaData.ImpliedNodeFormat == core.ModuleKindCommonJS {
17231725
if !spanCalculated {
17241726
span = scanner.GetRangeOfTokenAtPosition(sourceFile, node.Pos())
17251727
}

internal/compiler/emitHost.go

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/microsoft/typescript-go/internal/ast"
55
"github.com/microsoft/typescript-go/internal/core"
66
"github.com/microsoft/typescript-go/internal/printer"
7+
"github.com/microsoft/typescript-go/internal/tspath"
78
)
89

910
type WriteFileData struct {
@@ -23,6 +24,7 @@ type EmitHost interface {
2324
CommonSourceDirectory() string
2425
IsEmitBlocked(file string) bool
2526
WriteFile(fileName string, text string, writeByteOrderMark bool, relatedSourceFiles []*ast.SourceFile, data *WriteFileData) error
27+
GetSourceFileMetaData(path tspath.Path) *ast.SourceFileMetaData
2628
GetEmitResolver(file *ast.SourceFile, skipDiagnostics bool) printer.EmitResolver
2729
}
2830

@@ -54,3 +56,7 @@ func (host *emitHost) GetEmitResolver(file *ast.SourceFile, skipDiagnostics bool
5456
checker := host.program.GetTypeCheckerForFile(file)
5557
return checker.GetEmitResolver(file, skipDiagnostics)
5658
}
59+
60+
func (host *emitHost) GetSourceFileMetaData(path tspath.Path) *ast.SourceFileMetaData {
61+
return host.program.GetSourceFileMetaData(path)
62+
}

internal/compiler/emitter.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ func (e *emitter) emit() {
3838
e.emitBuildInfo(e.paths.buildInfoPath)
3939
}
4040

41-
func (e *emitter) getModuleTransformer(emitContext *printer.EmitContext, resolver binder.ReferenceResolver) *transformers.Transformer {
41+
func (e *emitter) getModuleTransformer(emitContext *printer.EmitContext, resolver binder.ReferenceResolver, sourceFileMetaDataProvider printer.SourceFileMetaDataProvider) *transformers.Transformer {
4242
options := e.host.Options()
4343

4444
switch options.GetEmitModuleKind() {
4545
case core.ModuleKindPreserve:
4646
// `ESModuleTransformer` contains logic for preserving CJS input syntax in `--module preserve`
47-
return transformers.NewESModuleTransformer(emitContext, options, resolver)
47+
return transformers.NewESModuleTransformer(emitContext, options, resolver, sourceFileMetaDataProvider)
4848

4949
case core.ModuleKindESNext,
5050
core.ModuleKindES2022,
@@ -53,10 +53,10 @@ func (e *emitter) getModuleTransformer(emitContext *printer.EmitContext, resolve
5353
core.ModuleKindNode16,
5454
core.ModuleKindNodeNext,
5555
core.ModuleKindCommonJS:
56-
return transformers.NewImpliedModuleTransformer(emitContext, options, resolver)
56+
return transformers.NewImpliedModuleTransformer(emitContext, options, resolver, sourceFileMetaDataProvider)
5757

5858
default:
59-
return transformers.NewCommonJSModuleTransformer(emitContext, options, resolver)
59+
return transformers.NewCommonJSModuleTransformer(emitContext, options, resolver, sourceFileMetaDataProvider)
6060
}
6161
}
6262

@@ -89,7 +89,7 @@ func (e *emitter) getScriptTransformers(emitContext *printer.EmitContext, source
8989
tx = append(tx, transformers.NewRuntimeSyntaxTransformer(emitContext, options, referenceResolver))
9090

9191
// transform module syntax
92-
tx = append(tx, e.getModuleTransformer(emitContext, referenceResolver))
92+
tx = append(tx, e.getModuleTransformer(emitContext, referenceResolver, e.host))
9393
return tx
9494
}
9595

internal/compiler/fileloader.go

+29-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ type fileLoader struct {
2323
resolvedModulesMutex sync.Mutex
2424
resolvedModules map[tspath.Path]module.ModeAwareCache[*module.ResolvedModule]
2525

26+
sourceFileMetaDatasMutex sync.RWMutex
27+
sourceFileMetaDatas map[tspath.Path]*ast.SourceFileMetaData
28+
2629
mu sync.Mutex
2730
wg core.WorkGroup
2831
tasksByFileName map[string]*parseTask
@@ -40,7 +43,7 @@ func processAllProgramFiles(
4043
resolver *module.Resolver,
4144
rootFiles []string,
4245
libs []string,
43-
) (files []*ast.SourceFile, resolvedModules map[tspath.Path]module.ModeAwareCache[*module.ResolvedModule]) {
46+
) (files []*ast.SourceFile, resolvedModules map[tspath.Path]module.ModeAwareCache[*module.ResolvedModule], sourceFileMetaDatas map[tspath.Path]*ast.SourceFileMetaData) {
4447
supportedExtensions := tsoptions.GetSupportedExtensions(compilerOptions, nil /*extraFileExtensions*/)
4548
loader := fileLoader{
4649
host: host,
@@ -76,7 +79,7 @@ func processAllProgramFiles(
7679
}
7780
loader.sortLibs(libFiles)
7881

79-
return append(libFiles, files...), loader.resolvedModules
82+
return append(libFiles, files...), loader.resolvedModules, loader.sourceFileMetaDatas
8083
}
8184

8285
func (p *fileLoader) addRootTasks(files []string, isLib bool) {
@@ -221,9 +224,33 @@ func (t *parseTask) start(loader *fileLoader) {
221224
})
222225
}
223226

227+
func (p *fileLoader) loadSourceFileMetaData(path tspath.Path) {
228+
p.sourceFileMetaDatasMutex.RLock()
229+
_, ok := p.sourceFileMetaDatas[path]
230+
p.sourceFileMetaDatasMutex.RUnlock()
231+
if ok {
232+
return
233+
}
234+
235+
packageJsonType := p.resolver.GetPackageJsonTypeIfApplicable(string(path))
236+
impliedNodeFormat := ast.GetImpliedNodeFormatForFile(string(path), packageJsonType)
237+
metadata := &ast.SourceFileMetaData{
238+
PackageJsonType: packageJsonType,
239+
ImpliedNodeFormat: impliedNodeFormat,
240+
}
241+
242+
p.sourceFileMetaDatasMutex.Lock()
243+
defer p.sourceFileMetaDatasMutex.Unlock()
244+
if p.sourceFileMetaDatas == nil {
245+
p.sourceFileMetaDatas = make(map[tspath.Path]*ast.SourceFileMetaData)
246+
}
247+
p.sourceFileMetaDatas[path] = metadata
248+
}
249+
224250
func (p *fileLoader) parseSourceFile(fileName string) *ast.SourceFile {
225251
path := tspath.ToPath(fileName, p.host.GetCurrentDirectory(), p.host.FS().UseCaseSensitiveFileNames())
226252
sourceFile := p.host.GetSourceFile(fileName, path, p.compilerOptions.GetEmitScriptTarget())
253+
p.loadSourceFileMetaData(path)
227254
return sourceFile
228255
}
229256

internal/compiler/module/resolver.go

+22
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,28 @@ func (r *Resolver) GetPackageScopeForPath(directory string) *packagejson.InfoCac
145145
return (&resolutionState{compilerOptions: r.compilerOptions, resolver: r}).getPackageScopeForPath(directory)
146146
}
147147

148+
func (r *Resolver) GetPackageJsonTypeIfApplicable(path string) string {
149+
if tspath.FileExtensionIsOneOf(path, []string{tspath.ExtensionMts, tspath.ExtensionCts, tspath.ExtensionMjs, tspath.ExtensionCjs}) {
150+
return ""
151+
}
152+
153+
var moduleResolutionKind core.ModuleResolutionKind
154+
if r.compilerOptions != nil {
155+
moduleResolutionKind = r.compilerOptions.GetModuleResolutionKind()
156+
}
157+
158+
var packageJsonType string
159+
shouldLookupFromPackageJson := core.ModuleResolutionKindNode16 <= moduleResolutionKind && moduleResolutionKind <= core.ModuleResolutionKindNodeNext || strings.Contains(path, "/node_modules/")
160+
if shouldLookupFromPackageJson {
161+
packageJsonScope := r.GetPackageScopeForPath(tspath.GetDirectoryPath(path))
162+
if packageJsonScope.Exists() {
163+
packageJsonType, _ = packageJsonScope.Contents.Type.GetValue()
164+
}
165+
}
166+
167+
return packageJsonType
168+
}
169+
148170
func (r *Resolver) ResolveTypeReferenceDirective(typeReferenceDirectiveName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference *ResolvedProjectReference) *ResolvedTypeReferenceDirective {
149171
traceEnabled := r.traceEnabled()
150172

internal/compiler/program.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ type Program struct {
4949
files []*ast.SourceFile
5050
filesByPath map[tspath.Path]*ast.SourceFile
5151

52+
sourceFileMetaDatas map[tspath.Path]*ast.SourceFileMetaData
53+
5254
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
5355
// This works as imported modules are discovered recursively in a depth first manner, specifically:
5456
// - For each root file, findSourceFile is called.
@@ -68,13 +70,12 @@ type Program struct {
6870
unsupportedExtensions []string
6971
}
7072

71-
var extensions = []string{".ts", ".tsx"}
72-
7373
func NewProgram(options ProgramOptions) *Program {
7474
p := &Program{}
7575
p.programOptions = options
7676
p.compilerOptions = options.Options
7777
p.configFileParsingDiagnostics = slices.Clip(options.ConfigFileParsingDiagnostics)
78+
p.sourceFileMetaDatas = make(map[tspath.Path]*ast.SourceFileMetaData)
7879
if p.compilerOptions == nil {
7980
p.compilerOptions = &core.CompilerOptions{}
8081
}
@@ -152,7 +153,7 @@ func NewProgram(options ProgramOptions) *Program {
152153
}
153154
}
154155

155-
p.files, p.resolvedModules = processAllProgramFiles(p.host, p.programOptions, p.compilerOptions, p.resolver, rootFiles, libs)
156+
p.files, p.resolvedModules, p.sourceFileMetaDatas = processAllProgramFiles(p.host, p.programOptions, p.compilerOptions, p.resolver, rootFiles, libs)
156157
p.filesByPath = make(map[tspath.Path]*ast.SourceFile, len(p.files))
157158
for _, file := range p.files {
158159
p.filesByPath[file.Path()] = file
@@ -456,16 +457,20 @@ func (p *Program) PrintSourceFileWithTypes() {
456457
}
457458
}
458459

460+
func (p *Program) GetSourceFileMetaData(path tspath.Path) *ast.SourceFileMetaData {
461+
return p.sourceFileMetaDatas[path]
462+
}
463+
459464
func (p *Program) GetEmitModuleFormatOfFile(sourceFile *ast.SourceFile) core.ModuleKind {
460465
return p.GetEmitModuleFormatOfFileWorker(sourceFile, p.compilerOptions)
461466
}
462467

463468
func (p *Program) GetEmitModuleFormatOfFileWorker(sourceFile *ast.SourceFile, options *core.CompilerOptions) core.ModuleKind {
464-
return ast.GetEmitModuleFormatOfFileWorker(sourceFile, options)
469+
return ast.GetEmitModuleFormatOfFileWorker(sourceFile, options, p.GetSourceFileMetaData(sourceFile.Path()))
465470
}
466471

467472
func (p *Program) GetImpliedNodeFormatForEmit(sourceFile *ast.SourceFile) core.ResolutionMode {
468-
return ast.GetImpliedNodeFormatForEmitWorker(sourceFile, p.compilerOptions)
473+
return ast.GetImpliedNodeFormatForEmitWorker(sourceFile.FileName(), p.compilerOptions, p.GetSourceFileMetaData(sourceFile.Path()))
469474
}
470475

471476
func (p *Program) CommonSourceDirectory() string {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package printer
2+
3+
import (
4+
"github.com/microsoft/typescript-go/internal/ast"
5+
"github.com/microsoft/typescript-go/internal/tspath"
6+
)
7+
8+
type SourceFileMetaDataProvider interface {
9+
GetSourceFileMetaData(path tspath.Path) *ast.SourceFileMetaData
10+
}

0 commit comments

Comments
 (0)