Skip to content

Commit 9cf6764

Browse files
authored
Implement externalModuleIndicator (#979)
1 parent 72d2ee6 commit 9cf6764

File tree

104 files changed

+581
-722
lines changed

Some content is hidden

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

104 files changed

+581
-722
lines changed

internal/api/encoder/encoder_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@ import (
1818
"gotest.tools/v3/assert"
1919
)
2020

21+
var parseCompilerOptions = &core.SourceFileAffectingCompilerOptions{
22+
EmitScriptTarget: core.ScriptTargetLatest,
23+
}
24+
2125
func TestEncodeSourceFile(t *testing.T) {
2226
t.Parallel()
23-
sourceFile := parser.ParseSourceFile("/test.ts", "/test.ts", "import { bar } from \"bar\";\nexport function foo<T, U>(a: string, b: string): any {}\nfoo();", core.ScriptTargetESNext, scanner.JSDocParsingModeParseAll)
27+
sourceFile := parser.ParseSourceFile("/test.ts", "/test.ts", "import { bar } from \"bar\";\nexport function foo<T, U>(a: string, b: string): any {}\nfoo();", parseCompilerOptions, nil, scanner.JSDocParsingModeParseAll)
2428
t.Run("baseline", func(t *testing.T) {
2529
t.Parallel()
2630
buf, err := encoder.EncodeSourceFile(sourceFile, "")
@@ -42,7 +46,8 @@ func BenchmarkEncodeSourceFile(b *testing.B) {
4246
"/checker.ts",
4347
"/checker.ts",
4448
string(fileContent),
45-
core.ScriptTargetESNext,
49+
parseCompilerOptions,
50+
nil,
4651
scanner.JSDocParsingModeParseAll,
4752
)
4853

internal/ast/ast.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10008,6 +10008,8 @@ type SourceFile struct {
1000810008
CheckJsDirective *CheckJsDirective
1000910009
NodeCount int
1001010010
TextCount int
10011+
CommonJSModuleIndicator *Node
10012+
ExternalModuleIndicator *Node
1001110013

1001210014
// Fields set by binder
1001310015

@@ -10030,11 +10032,7 @@ type SourceFile struct {
1003010032
tokenCacheMu sync.Mutex
1003110033
tokenCache map[core.TextRange]*Node
1003210034

10033-
// !!!
10034-
10035-
CommonJSModuleIndicator *Node
10036-
ExternalModuleIndicator *Node
10037-
JSGlobalAugmentations SymbolTable
10035+
JSGlobalAugmentations SymbolTable // !!! remove me
1003810036
}
1003910037

1004010038
func (f *NodeFactory) NewSourceFile(text string, fileName string, path tspath.Path, statements *NodeList) *Node {

internal/ast/utilities.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,16 +2514,15 @@ func GetImpliedNodeFormatForFile(path string, packageJsonType string) core.Modul
25142514
}
25152515

25162516
func GetEmitModuleFormatOfFileWorker(fileName string, options *core.CompilerOptions, sourceFileMetaData *SourceFileMetaData) core.ModuleKind {
2517-
result := GetImpliedNodeFormatForEmitWorker(fileName, options, sourceFileMetaData)
2517+
result := GetImpliedNodeFormatForEmitWorker(fileName, options.GetEmitModuleKind(), sourceFileMetaData)
25182518
if result != core.ModuleKindNone {
25192519
return result
25202520
}
25212521
return options.GetEmitModuleKind()
25222522
}
25232523

2524-
func GetImpliedNodeFormatForEmitWorker(fileName string, options *core.CompilerOptions, sourceFileMetaData *SourceFileMetaData) core.ResolutionMode {
2525-
moduleKind := options.GetEmitModuleKind()
2526-
if core.ModuleKindNode16 <= moduleKind && moduleKind <= core.ModuleKindNodeNext {
2524+
func GetImpliedNodeFormatForEmitWorker(fileName string, emitModuleKind core.ModuleKind, sourceFileMetaData *SourceFileMetaData) core.ResolutionMode {
2525+
if core.ModuleKindNode16 <= emitModuleKind && emitModuleKind <= core.ModuleKindNodeNext {
25272526
if sourceFileMetaData == nil {
25282527
return core.ModuleKindNone
25292528
}

internal/astnav/tokens_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ var testFiles = []string{
2626
filepath.Join(repo.TypeScriptSubmodulePath, "src/services/mapCode.ts"),
2727
}
2828

29+
var parseCompilerOptions = &core.SourceFileAffectingCompilerOptions{
30+
EmitScriptTarget: core.ScriptTargetLatest,
31+
}
32+
2933
func TestGetTokenAtPosition(t *testing.T) {
3034
t.Parallel()
3135
repo.SkipIfNoTypeScriptSubmodule(t)
@@ -53,7 +57,7 @@ func TestGetTokenAtPosition(t *testing.T) {
5357
return 0;
5458
}
5559
`
56-
file := parser.ParseSourceFile("/file.ts", "/file.ts", fileText, core.ScriptTargetLatest, scanner.JSDocParsingModeParseAll)
60+
file := parser.ParseSourceFile("/file.ts", "/file.ts", fileText, parseCompilerOptions, nil, scanner.JSDocParsingModeParseAll)
5761
assert.Equal(t, astnav.GetTokenAtPosition(file, 0), astnav.GetTokenAtPosition(file, 0))
5862
})
5963
}
@@ -88,7 +92,7 @@ func baselineTokens(t *testing.T, testName string, includeEOF bool, getTSTokens
8892
positions[i] = i
8993
}
9094
tsTokens := getTSTokens(string(fileText), positions)
91-
file := parser.ParseSourceFile("/file.ts", "/file.ts", string(fileText), core.ScriptTargetLatest, scanner.JSDocParsingModeParseAll)
95+
file := parser.ParseSourceFile("/file.ts", "/file.ts", string(fileText), parseCompilerOptions, nil, scanner.JSDocParsingModeParseAll)
9296

9397
var output strings.Builder
9498
currentRange := core.NewTextRange(0, 0)
@@ -421,7 +425,7 @@ export function isAnyDirectorySeparator(charCode: number): boolean {
421425
for _, testCase := range testCases {
422426
t.Run(testCase.name, func(t *testing.T) {
423427
t.Parallel()
424-
file := parser.ParseSourceFile("/file.ts", "/file.ts", testCase.fileContent, core.ScriptTargetLatest, scanner.JSDocParsingModeParseAll)
428+
file := parser.ParseSourceFile("/file.ts", "/file.ts", testCase.fileContent, parseCompilerOptions, nil, scanner.JSDocParsingModeParseAll)
425429
token := astnav.FindPrecedingToken(file, testCase.position)
426430
assert.Equal(t, token.Kind, testCase.expectedKind)
427431
})

internal/binder/binder_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ func BenchmarkBind(b *testing.B) {
2222
path := tspath.ToPath(fileName, "/", osvfs.FS().UseCaseSensitiveFileNames())
2323
sourceText := f.ReadFile(b)
2424

25+
compilerOptions := &core.CompilerOptions{Target: core.ScriptTargetESNext, Module: core.ModuleKindNodeNext}
26+
sourceAffecting := compilerOptions.SourceFileAffecting()
27+
2528
sourceFiles := make([]*ast.SourceFile, b.N)
2629
for i := range b.N {
27-
sourceFiles[i] = parser.ParseSourceFile(fileName, path, sourceText, core.ScriptTargetESNext, scanner.JSDocParsingModeParseAll)
30+
sourceFiles[i] = parser.ParseSourceFile(fileName, path, sourceText, sourceAffecting, nil, scanner.JSDocParsingModeParseAll)
2831
}
2932

30-
compilerOptions := &core.CompilerOptions{Target: core.ScriptTargetESNext, Module: core.ModuleKindNodeNext}
31-
sourceAffecting := compilerOptions.SourceFileAffecting()
32-
3333
// The above parses do a lot of work; ensure GC is finished before we start collecting performance data.
3434
// GC must be called twice to allow things to settle.
3535
runtime.GC()

internal/compiler/fileloader.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,13 @@ func (t *parseTask) start(loader *fileLoader) {
244244
}
245245

246246
loader.wg.Queue(func() {
247-
file := loader.parseSourceFile(t.normalizedFilePath)
247+
t.metadata = loader.loadSourceFileMetaData(t.normalizedFilePath)
248+
file := loader.parseSourceFile(t.normalizedFilePath, t.metadata)
248249
if file == nil {
249250
return
250251
}
251252

252253
t.file = file
253-
t.metadata = loader.loadSourceFileMetaData(file.FileName())
254254

255255
// !!! if noResolve, skip all of this
256256
t.subTasks = make([]*parseTask, 0, len(file.ReferencedFiles)+len(file.Imports())+len(file.ModuleAugmentations))
@@ -309,9 +309,9 @@ func (p *fileLoader) loadSourceFileMetaData(fileName string) *ast.SourceFileMeta
309309
}
310310
}
311311

312-
func (p *fileLoader) parseSourceFile(fileName string) *ast.SourceFile {
312+
func (p *fileLoader) parseSourceFile(fileName string, metadata *ast.SourceFileMetaData) *ast.SourceFile {
313313
path := tspath.ToPath(fileName, p.opts.Host.GetCurrentDirectory(), p.opts.Host.FS().UseCaseSensitiveFileNames())
314-
sourceFile := p.opts.Host.GetSourceFile(fileName, path, p.opts.Config.CompilerOptions().GetEmitScriptTarget())
314+
sourceFile := p.opts.Host.GetSourceFile(fileName, path, p.opts.Config.CompilerOptions().SourceFileAffecting(), metadata) // TODO(jakebailey): cache :(
315315
return sourceFile
316316
}
317317

@@ -467,7 +467,7 @@ func getModeForTypeReferenceDirectiveInFile(ref *ast.FileReference, file *ast.So
467467

468468
func getDefaultResolutionModeForFile(fileName string, meta *ast.SourceFileMetaData, options *core.CompilerOptions) core.ResolutionMode {
469469
if importSyntaxAffectsModuleResolution(options) {
470-
return ast.GetImpliedNodeFormatForEmitWorker(fileName, options, meta)
470+
return ast.GetImpliedNodeFormatForEmitWorker(fileName, options.GetEmitModuleKind(), meta)
471471
} else {
472472
return core.ResolutionModeNone
473473
}

internal/compiler/host.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type CompilerHost interface {
1616
GetCurrentDirectory() string
1717
NewLine() string
1818
Trace(msg string)
19-
GetSourceFile(fileName string, path tspath.Path, languageVersion core.ScriptTarget) *ast.SourceFile
19+
GetSourceFile(fileName string, path tspath.Path, options *core.SourceFileAffectingCompilerOptions, metadata *ast.SourceFileMetaData) *ast.SourceFile
2020
}
2121

2222
type FileInfo struct {
@@ -73,10 +73,10 @@ func (h *compilerHost) Trace(msg string) {
7373
//!!! TODO: implement
7474
}
7575

76-
func (h *compilerHost) GetSourceFile(fileName string, path tspath.Path, languageVersion core.ScriptTarget) *ast.SourceFile {
76+
func (h *compilerHost) GetSourceFile(fileName string, path tspath.Path, options *core.SourceFileAffectingCompilerOptions, metadata *ast.SourceFileMetaData) *ast.SourceFile {
7777
text, _ := h.FS().ReadFile(fileName)
7878
if tspath.FileExtensionIs(fileName, tspath.ExtensionJson) {
7979
return parser.ParseJSONText(fileName, path, text)
8080
}
81-
return parser.ParseSourceFile(fileName, path, text, languageVersion, scanner.JSDocParsingModeParseForTypeErrors)
81+
return parser.ParseSourceFile(fileName, path, text, options, metadata, scanner.JSDocParsingModeParseForTypeErrors)
8282
}

internal/compiler/program.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ func NewProgram(opts ProgramOptions) *Program {
228228
// In addition to a new program, return a boolean indicating whether the data of the old program was reused.
229229
func (p *Program) UpdateProgram(changedFilePath tspath.Path) (*Program, bool) {
230230
oldFile := p.filesByPath[changedFilePath]
231-
newFile := p.Host().GetSourceFile(oldFile.FileName(), changedFilePath, oldFile.LanguageVersion)
231+
// TODO(jakebailey): is wrong because the new file may have new metadata?
232+
metadata := p.sourceFileMetaDatas[changedFilePath]
233+
newFile := p.Host().GetSourceFile(oldFile.FileName(), changedFilePath, p.Options().SourceFileAffecting(), metadata)
232234
if !canReplaceFileInProgram(oldFile, newFile) {
233235
return NewProgram(p.opts), false
234236
}
@@ -262,6 +264,7 @@ func (p *Program) initCheckerPool() {
262264
}
263265

264266
func canReplaceFileInProgram(file1 *ast.SourceFile, file2 *ast.SourceFile) bool {
267+
// TODO(jakebailey): metadata??
265268
return file1.FileName() == file2.FileName() &&
266269
file1.Path() == file2.Path() &&
267270
file1.LanguageVersion == file2.LanguageVersion &&
@@ -696,7 +699,7 @@ func (p *Program) GetEmitSyntaxForUsageLocation(sourceFile ast.HasFileName, loca
696699
}
697700

698701
func (p *Program) GetImpliedNodeFormatForEmit(sourceFile ast.HasFileName) core.ResolutionMode {
699-
return ast.GetImpliedNodeFormatForEmitWorker(sourceFile.FileName(), p.Options(), p.GetSourceFileMetaData(sourceFile.Path()))
702+
return ast.GetImpliedNodeFormatForEmitWorker(sourceFile.FileName(), p.Options().GetEmitModuleKind(), p.GetSourceFileMetaData(sourceFile.Path()))
700703
}
701704

702705
func (p *Program) GetModeForUsageLocation(sourceFile ast.HasFileName, location *ast.StringLiteralLike) core.ResolutionMode {

internal/core/compileroptions.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,18 @@ func (options *CompilerOptions) GetModuleResolutionKind() ModuleResolutionKind {
216216
}
217217
}
218218

219+
func (options *CompilerOptions) GetEmitModuleDetectionKind() ModuleDetectionKind {
220+
if options.ModuleDetection != ModuleDetectionKindNone {
221+
return options.ModuleDetection
222+
}
223+
switch options.GetEmitModuleKind() {
224+
case ModuleKindNode16, ModuleKindNodeNext:
225+
return ModuleDetectionKindForce
226+
default:
227+
return ModuleDetectionKindAuto
228+
}
229+
}
230+
219231
func (options *CompilerOptions) GetResolvePackageJsonExports() bool {
220232
return options.ResolvePackageJsonExports.IsTrueOrUnknown()
221233
}
@@ -339,7 +351,10 @@ type SourceFileAffectingCompilerOptions struct {
339351
AllowUnreachableCode Tristate
340352
AllowUnusedLabels Tristate
341353
BindInStrictMode bool
354+
EmitModuleDetectionKind ModuleDetectionKind
355+
EmitModuleKind ModuleKind
342356
EmitScriptTarget ScriptTarget
357+
JsxEmit JsxEmit
343358
NoFallthroughCasesInSwitch Tristate
344359
ShouldPreserveConstEnums bool
345360
}
@@ -349,7 +364,10 @@ func (options *CompilerOptions) SourceFileAffecting() *SourceFileAffectingCompil
349364
AllowUnreachableCode: options.AllowUnreachableCode,
350365
AllowUnusedLabels: options.AllowUnusedLabels,
351366
BindInStrictMode: options.AlwaysStrict.IsTrue() || options.Strict.IsTrue(),
367+
EmitModuleDetectionKind: options.GetEmitModuleDetectionKind(),
368+
EmitModuleKind: options.GetEmitModuleKind(),
352369
EmitScriptTarget: options.GetEmitScriptTarget(),
370+
JsxEmit: options.Jsx,
353371
NoFallthroughCasesInSwitch: options.NoFallthroughCasesInSwitch,
354372
ShouldPreserveConstEnums: options.ShouldPreserveConstEnums(),
355373
}

internal/format/api_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ func applyBulkEdits(text string, edits []core.TextChange) string {
3434
return b.String()
3535
}
3636

37+
var parseCompilerOptions = &core.SourceFileAffectingCompilerOptions{
38+
EmitScriptTarget: core.ScriptTargetLatest,
39+
}
40+
3741
func TestFormat(t *testing.T) {
3842
t.Parallel()
3943

@@ -60,7 +64,8 @@ func TestFormat(t *testing.T) {
6064
"/checker.ts",
6165
"/checker.ts",
6266
text,
63-
core.ScriptTargetESNext,
67+
parseCompilerOptions,
68+
nil,
6469
scanner.JSDocParsingModeParseAll,
6570
)
6671
ast.SetParentInChildren(sourceFile.AsNode())
@@ -93,7 +98,8 @@ func BenchmarkFormat(b *testing.B) {
9398
"/checker.ts",
9499
"/checker.ts",
95100
text,
96-
core.ScriptTargetESNext,
101+
parseCompilerOptions,
102+
nil,
97103
scanner.JSDocParsingModeParseAll,
98104
)
99105
ast.SetParentInChildren(sourceFile.AsNode())

0 commit comments

Comments
 (0)