From 443de4e7816587d4f30e67a6056ca832ec0575de Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 10 Nov 2025 12:39:19 -0800 Subject: [PATCH 1/6] incremental compiler tests use the incremental builder program emit pipeline --- internal/compiler/program.go | 4 +++ internal/execute/incremental/program.go | 24 ++++++++++++++ internal/testrunner/compiler_runner.go | 15 ++++++++- internal/testutil/harnessutil/harnessutil.go | 31 ++++++++++++------- .../testutil/tsbaseline/js_emit_baseline.go | 2 +- .../tsbaseline/type_symbol_baseline.go | 15 ++++++--- 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/internal/compiler/program.go b/internal/compiler/program.go index ce89aaa601..6f39db2c4f 100644 --- a/internal/compiler/program.go +++ b/internal/compiler/program.go @@ -1437,6 +1437,7 @@ func CombineEmitResults(results []*EmitResult) *EmitResult { type ProgramLike interface { Options() *core.CompilerOptions + GetSourceFile(path string) *ast.SourceFile GetSourceFiles() []*ast.SourceFile GetConfigFileParsingDiagnostics() []*ast.Diagnostic GetSyntacticDiagnostics(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic @@ -1446,7 +1447,10 @@ type ProgramLike interface { GetGlobalDiagnostics(ctx context.Context) []*ast.Diagnostic GetSemanticDiagnostics(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic GetDeclarationDiagnostics(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic + GetSuggestionDiagnostics(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic Emit(ctx context.Context, options EmitOptions) *EmitResult + CommonSourceDirectory() string + IsSourceFileDefaultLibrary(path tspath.Path) bool } func HandleNoEmitOnError(ctx context.Context, program ProgramLike, file *ast.SourceFile) *EmitResult { diff --git a/internal/execute/incremental/program.go b/internal/execute/incremental/program.go index ceac9c35d4..e91e889bbb 100644 --- a/internal/execute/incremental/program.go +++ b/internal/execute/incremental/program.go @@ -84,12 +84,30 @@ func (p *Program) Options() *core.CompilerOptions { return p.snapshot.options } +// CommonSourceDirectory implements compiler.AnyProgram interface. +func (p *Program) CommonSourceDirectory() string { + p.panicIfNoProgram("CommonSourceDirectory") + return p.program.CommonSourceDirectory() +} + +// IsSourceFileDefaultLibrary implements compiler.AnyProgram interface. +func (p *Program) IsSourceFileDefaultLibrary(path tspath.Path) bool { + p.panicIfNoProgram("IsSourceFileDefaultLibrary") + return p.program.IsSourceFileDefaultLibrary(path) +} + // GetSourceFiles implements compiler.AnyProgram interface. func (p *Program) GetSourceFiles() []*ast.SourceFile { p.panicIfNoProgram("GetSourceFiles") return p.program.GetSourceFiles() } +// GetSourceFile implements compiler.AnyProgram interface. +func (p *Program) GetSourceFile(path string) *ast.SourceFile { + p.panicIfNoProgram("GetSourceFile") + return p.program.GetSourceFile(path) +} + // GetConfigFileParsingDiagnostics implements compiler.AnyProgram interface. func (p *Program) GetConfigFileParsingDiagnostics() []*ast.Diagnostic { p.panicIfNoProgram("GetConfigFileParsingDiagnostics") @@ -172,6 +190,12 @@ func (p *Program) GetDeclarationDiagnostics(ctx context.Context, file *ast.Sourc return nil } +// GetSuggestionDiagnostics implements compiler.AnyProgram interface. +func (p *Program) GetSuggestionDiagnostics(ctx context.Context, file *ast.SourceFile) []*ast.Diagnostic { + p.panicIfNoProgram("GetSuggestionDiagnostics") + return p.program.GetSuggestionDiagnostics(ctx, file) // TODO: incremental suggestion diagnostics (only relevant in editor incremental builder?) +} + // GetModeForUsageLocation implements compiler.AnyProgram interface. func (p *Program) Emit(ctx context.Context, options compiler.EmitOptions) *compiler.EmitResult { p.panicIfNoProgram("Emit") diff --git a/internal/testrunner/compiler_runner.go b/internal/testrunner/compiler_runner.go index 5b86188001..8f2789382c 100644 --- a/internal/testrunner/compiler_runner.go +++ b/internal/testrunner/compiler_runner.go @@ -12,7 +12,9 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/checker" + "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/execute/incremental" "github.com/microsoft/typescript-go/internal/repo" "github.com/microsoft/typescript-go/internal/testutil" "github.com/microsoft/typescript-go/internal/testutil/baseline" @@ -528,7 +530,18 @@ func createHarnessTestFile(unit *testUnit, currentDirectory string) *harnessutil func (c *compilerTest) verifyUnionOrdering(t *testing.T) { t.Run("union ordering", func(t *testing.T) { - checkers, done := c.result.Program.GetTypeCheckers(t.Context()) + var p *compiler.Program + switch desugared := c.result.Program.(type) { + case *compiler.Program: + { + p = desugared + } + case *incremental.Program: + { + p = desugared.GetProgram() + } + } + checkers, done := p.GetTypeCheckers(t.Context()) defer done() for _, c := range checkers { for union := range c.UnionTypes() { diff --git a/internal/testutil/harnessutil/harnessutil.go b/internal/testutil/harnessutil/harnessutil.go index f88e72048d..52c229db8d 100644 --- a/internal/testutil/harnessutil/harnessutil.go +++ b/internal/testutil/harnessutil/harnessutil.go @@ -21,6 +21,7 @@ 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/execute/incremental" "github.com/microsoft/typescript-go/internal/outputpaths" "github.com/microsoft/typescript-go/internal/parser" "github.com/microsoft/typescript-go/internal/repo" @@ -687,13 +688,13 @@ func compileFilesWithHost( } emitResult := program.Emit(ctx, compiler.EmitOptions{}) - return newCompilationResult(config.CompilerOptions(), program, emitResult, diagnostics, harnessOptions) + return newCompilationResult(host, config.CompilerOptions(), program, emitResult, diagnostics, harnessOptions) } type CompilationResult struct { Diagnostics []*ast.Diagnostic Result *compiler.EmitResult - Program *compiler.Program + Program compiler.ProgramLike Options *core.CompilerOptions HarnessOptions *HarnessOptions JS collections.OrderedMap[string, *TestFile] @@ -705,6 +706,7 @@ type CompilationResult struct { inputs []*TestFile inputsAndOutputs collections.OrderedMap[string, *CompilationOutput] Trace string + Host compiler.CompilerHost } type CompilationOutput struct { @@ -715,8 +717,9 @@ type CompilationOutput struct { } func newCompilationResult( + host compiler.CompilerHost, options *core.CompilerOptions, - program *compiler.Program, + program compiler.ProgramLike, result *compiler.EmitResult, diagnostics []*ast.Diagnostic, harnessOptions *HarnessOptions, @@ -731,9 +734,10 @@ func newCompilationResult( Program: program, Options: options, HarnessOptions: harnessOptions, + Host: host, } - fs := program.Host().FS().(*OutputRecorderFS) + fs := host.FS().(*OutputRecorderFS) if fs != nil && program != nil { // Corsa, unlike Strada, can use multiple threads for emit. As a result, the order of outputs is non-deterministic. // To make the order deterministic, we sort the outputs by the order of the inputs. @@ -803,7 +807,7 @@ func compareTestFiles(a *TestFile, b *TestFile) int { } func (c *CompilationResult) getOutputPath(path string, ext string) string { - path = tspath.ResolvePath(c.Program.GetCurrentDirectory(), path) + path = tspath.ResolvePath(c.Host.GetCurrentDirectory(), path) var outDir string if ext == ".d.ts" || ext == ".d.mts" || ext == ".d.cts" || (strings.HasSuffix(ext, ".ts") && strings.Contains(ext, ".d.")) { outDir = c.Options.DeclarationDir @@ -817,17 +821,17 @@ func (c *CompilationResult) getOutputPath(path string, ext string) string { common := c.Program.CommonSourceDirectory() if common != "" { path = tspath.GetRelativePathFromDirectory(common, path, tspath.ComparePathsOptions{ - UseCaseSensitiveFileNames: c.Program.UseCaseSensitiveFileNames(), - CurrentDirectory: c.Program.GetCurrentDirectory(), + UseCaseSensitiveFileNames: c.Host.FS().UseCaseSensitiveFileNames(), + CurrentDirectory: c.Host.GetCurrentDirectory(), }) - path = tspath.CombinePaths(tspath.ResolvePath(c.Program.GetCurrentDirectory(), c.Options.OutDir), path) + path = tspath.CombinePaths(tspath.ResolvePath(c.Host.GetCurrentDirectory(), c.Options.OutDir), path) } } return tspath.ChangeExtension(path, ext) } func (r *CompilationResult) FS() vfs.FS { - return r.Program.Host().FS() + return r.Host.FS() } func (r *CompilationResult) GetNumberOfJSFiles(includeJson bool) int { @@ -852,7 +856,7 @@ func (c *CompilationResult) Outputs() []*TestFile { } func (c *CompilationResult) GetInputsAndOutputsForFile(path string) *CompilationOutput { - return c.inputsAndOutputs.GetOrZero(tspath.ResolvePath(c.Program.GetCurrentDirectory(), path)) + return c.inputsAndOutputs.GetOrZero(tspath.ResolvePath(c.Host.GetCurrentDirectory(), path)) } func (c *CompilationResult) GetInputsForFile(path string) []*TestFile { @@ -915,7 +919,7 @@ func (c *CompilationResult) GetSourceMapRecord() string { return sourceMapRecorder.String() } -func createProgram(host compiler.CompilerHost, config *tsoptions.ParsedCommandLine) *compiler.Program { +func createProgram(host compiler.CompilerHost, config *tsoptions.ParsedCommandLine) compiler.ProgramLike { var singleThreaded core.Tristate if testutil.TestProgramIsSingleThreaded() { singleThreaded = core.TSTrue @@ -927,6 +931,11 @@ func createProgram(host compiler.CompilerHost, config *tsoptions.ParsedCommandLi SingleThreaded: singleThreaded, } program := compiler.NewProgram(programOptions) + if config.CompilerOptions().Incremental.IsTrue() { + oldProgram := incremental.ReadBuildInfoProgram(config, incremental.NewBuildInfoReader(host), host) + incrementalProgram := incremental.NewProgram(program, oldProgram, incremental.CreateHost(host), false) + return incrementalProgram + } return program } diff --git a/internal/testutil/tsbaseline/js_emit_baseline.go b/internal/testutil/tsbaseline/js_emit_baseline.go index 8b51c19349..fc4bced86a 100644 --- a/internal/testutil/tsbaseline/js_emit_baseline.go +++ b/internal/testutil/tsbaseline/js_emit_baseline.go @@ -201,7 +201,7 @@ func prepareDeclarationCompilationContext( var sourceFileName string if len(options.OutDir) != 0 { - sourceFilePath := tspath.GetNormalizedAbsolutePath(sourceFile.FileName(), result.Program.GetCurrentDirectory()) + sourceFilePath := tspath.GetNormalizedAbsolutePath(sourceFile.FileName(), result.Host.GetCurrentDirectory()) sourceFilePath = strings.Replace(sourceFilePath, result.Program.CommonSourceDirectory(), "", 1) sourceFileName = tspath.CombinePaths(options.OutDir, sourceFilePath) } else { diff --git a/internal/testutil/tsbaseline/type_symbol_baseline.go b/internal/testutil/tsbaseline/type_symbol_baseline.go index f08dbf37b4..d2efcf862f 100644 --- a/internal/testutil/tsbaseline/type_symbol_baseline.go +++ b/internal/testutil/tsbaseline/type_symbol_baseline.go @@ -12,6 +12,7 @@ import ( "github.com/microsoft/typescript-go/internal/checker" "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/execute/incremental" "github.com/microsoft/typescript-go/internal/nodebuilder" "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/scanner" @@ -31,7 +32,7 @@ func DoTypeAndSymbolBaseline( t *testing.T, baselinePath string, header string, - program *compiler.Program, + program compiler.ProgramLike, allFiles []*harnessutil.TestFile, opts baseline.Options, skipTypeBaselines bool, @@ -259,13 +260,13 @@ func iterateBaseline(allFiles []*harnessutil.TestFile, fullWalker *typeWriterWal } type typeWriterWalker struct { - program *compiler.Program + program compiler.ProgramLike hadErrorBaseline bool currentSourceFile *ast.SourceFile declarationTextCache map[*ast.Node]string } -func newTypeWriterWalker(program *compiler.Program, hadErrorBaseline bool) *typeWriterWalker { +func newTypeWriterWalker(program compiler.ProgramLike, hadErrorBaseline bool) *typeWriterWalker { return &typeWriterWalker{ program: program, hadErrorBaseline: hadErrorBaseline, @@ -276,7 +277,13 @@ func newTypeWriterWalker(program *compiler.Program, hadErrorBaseline bool) *type func (walker *typeWriterWalker) getTypeCheckerForCurrentFile() (*checker.Checker, func()) { // If we don't use the right checker for the file, its contents won't be up to date // since the types/symbols baselines appear to depend on files having been checked. - return walker.program.GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) + switch p := walker.program.(type) { + case *compiler.Program: + return p.GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) + case *incremental.Program: + return p.GetProgram().GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) + } + panic("unknown program kind, cannot get checker for file") } type typeWriterResult struct { From 2b0ad78c3d0a1703ff801ab75724dff3815bd998 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 10 Nov 2025 14:29:43 -0800 Subject: [PATCH 2/6] Add test triggering data race under -race, fix with optional exclusive checker access tracked by checker pools --- internal/compiler/checkerpool.go | 13 + internal/compiler/program.go | 6 + .../incremental/affectedfileshandler.go | 2 +- internal/project/checkerpool.go | 20 ++ internal/testutil/harnessutil/harnessutil.go | 19 +- ...incrementalConcurrentSafeAliasFollowing.js | 295 ++++++++++++++++++ ...mentalConcurrentSafeAliasFollowing.symbols | 151 +++++++++ ...rementalConcurrentSafeAliasFollowing.types | 152 +++++++++ ...incrementalConcurrentSafeAliasFollowing.ts | 147 +++++++++ 9 files changed, 803 insertions(+), 2 deletions(-) create mode 100644 testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.js create mode 100644 testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.symbols create mode 100644 testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.types create mode 100644 testdata/tests/cases/compiler/incrementalConcurrentSafeAliasFollowing.ts diff --git a/internal/compiler/checkerpool.go b/internal/compiler/checkerpool.go index 9b32992f20..9e0fe4e0cb 100644 --- a/internal/compiler/checkerpool.go +++ b/internal/compiler/checkerpool.go @@ -14,6 +14,7 @@ import ( type CheckerPool interface { GetChecker(ctx context.Context) (*checker.Checker, func()) GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) + GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) GetAllCheckers(ctx context.Context) ([]*checker.Checker, func()) Files(checker *checker.Checker) iter.Seq[*ast.SourceFile] } @@ -24,6 +25,7 @@ type checkerPool struct { createCheckersOnce sync.Once checkers []*checker.Checker + locks []sync.Mutex fileAssociations map[*ast.SourceFile]*checker.Checker } @@ -34,6 +36,7 @@ func newCheckerPool(checkerCount int, program *Program) *checkerPool { program: program, checkerCount: checkerCount, checkers: make([]*checker.Checker, checkerCount), + locks: make([]sync.Mutex, checkerCount), } return pool @@ -45,6 +48,16 @@ func (p *checkerPool) GetCheckerForFile(ctx context.Context, file *ast.SourceFil return checker, noop } +func (p *checkerPool) GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { + c, done := p.GetCheckerForFile(ctx, file) + idx := slices.Index(p.checkers, c) + p.locks[idx].Lock() + return c, sync.OnceFunc(func() { + p.locks[idx].Unlock() + done() + }) +} + func (p *checkerPool) GetChecker(ctx context.Context) (*checker.Checker, func()) { p.createCheckers() checker := p.checkers[0] diff --git a/internal/compiler/program.go b/internal/compiler/program.go index 6f39db2c4f..59641bfa75 100644 --- a/internal/compiler/program.go +++ b/internal/compiler/program.go @@ -383,6 +383,12 @@ func (p *Program) GetTypeCheckerForFile(ctx context.Context, file *ast.SourceFil return p.checkerPool.GetCheckerForFile(ctx, file) } +// Return a checker for the given file, locked to the current thread to prevent data races from multiple threads +// accessing the same checker. The lock will be released when the `done` function is called. +func (p *Program) GetTypeCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { + return p.checkerPool.GetCheckerForFileExclusive(ctx, file) +} + func (p *Program) GetResolvedModule(file ast.HasFileName, moduleReference string, mode core.ResolutionMode) *module.ResolvedModule { if resolutions, ok := p.resolvedModules[file.Path()]; ok { if resolved, ok := resolutions[module.ModeAwareCacheKey{Name: moduleReference, Mode: mode}]; ok { diff --git a/internal/execute/incremental/affectedfileshandler.go b/internal/execute/incremental/affectedfileshandler.go index 355b58aec8..ed82d52f5c 100644 --- a/internal/execute/incremental/affectedfileshandler.go +++ b/internal/execute/incremental/affectedfileshandler.go @@ -229,7 +229,7 @@ func (h *affectedFilesHandler) handleDtsMayChangeOfAffectedFile(dtsMayChange dts break } if typeChecker == nil { - typeChecker, done = h.program.program.GetTypeCheckerForFile(h.ctx, affectedFile) + typeChecker, done = h.program.program.GetTypeCheckerForFileExclusive(h.ctx, affectedFile) } aliased := checker.SkipAlias(exported, typeChecker) if aliased == exported { diff --git a/internal/project/checkerpool.go b/internal/project/checkerpool.go index 017fd2fbee..92e51e8829 100644 --- a/internal/project/checkerpool.go +++ b/internal/project/checkerpool.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "iter" + "slices" "sync" "github.com/microsoft/typescript-go/internal/ast" @@ -20,6 +21,7 @@ type CheckerPool struct { cond *sync.Cond createCheckersOnce sync.Once checkers []*checker.Checker + locks []sync.Mutex inUse map[*checker.Checker]bool fileAssociations map[*ast.SourceFile]int requestAssociations map[string]int @@ -33,6 +35,7 @@ func newCheckerPool(maxCheckers int, program *compiler.Program, log func(msg str program: program, maxCheckers: maxCheckers, checkers: make([]*checker.Checker, maxCheckers), + locks: make([]sync.Mutex, maxCheckers), inUse: make(map[*checker.Checker]bool), requestAssociations: make(map[string]int), log: log, @@ -75,6 +78,23 @@ func (p *CheckerPool) GetCheckerForFile(ctx context.Context, file *ast.SourceFil return checker, p.createRelease(requestID, index, checker) } +// GetCheckerForFileExclusive is the same as GetCheckerForFile but also locks a mutex associated with the checker. +// Call `done` to free the lock. +func (p *CheckerPool) GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { + c, done := p.GetCheckerForFile(ctx, file) + p.mu.Lock() + defer p.mu.Unlock() + + idx := slices.Index(p.checkers, c) + p.locks[idx].Lock() + return c, sync.OnceFunc(func() { + done() + p.mu.Lock() + defer p.mu.Unlock() + p.locks[idx].Unlock() + }) +} + func (p *CheckerPool) GetChecker(ctx context.Context) (*checker.Checker, func()) { p.mu.Lock() defer p.mu.Unlock() diff --git a/internal/testutil/harnessutil/harnessutil.go b/internal/testutil/harnessutil/harnessutil.go index 52c229db8d..ae0d04f040 100644 --- a/internal/testutil/harnessutil/harnessutil.go +++ b/internal/testutil/harnessutil/harnessutil.go @@ -919,6 +919,23 @@ func (c *CompilationResult) GetSourceMapRecord() string { return sourceMapRecorder.String() } +type testBuildInfoReader struct { + inner incremental.BuildInfoReader +} + +func (t *testBuildInfoReader) ReadBuildInfo(config *tsoptions.ParsedCommandLine) *incremental.BuildInfo { + r := t.inner.ReadBuildInfo(config) + if r == nil { + return nil + } + r.Version = core.Version() + return r +} + +func getTestBuildInfoReader(host compiler.CompilerHost) *testBuildInfoReader { + return &testBuildInfoReader{inner: incremental.NewBuildInfoReader(host)} +} + func createProgram(host compiler.CompilerHost, config *tsoptions.ParsedCommandLine) compiler.ProgramLike { var singleThreaded core.Tristate if testutil.TestProgramIsSingleThreaded() { @@ -932,7 +949,7 @@ func createProgram(host compiler.CompilerHost, config *tsoptions.ParsedCommandLi } program := compiler.NewProgram(programOptions) if config.CompilerOptions().Incremental.IsTrue() { - oldProgram := incremental.ReadBuildInfoProgram(config, incremental.NewBuildInfoReader(host), host) + oldProgram := incremental.ReadBuildInfoProgram(config, getTestBuildInfoReader(host), host) incrementalProgram := incremental.NewProgram(program, oldProgram, incremental.CreateHost(host), false) return incrementalProgram } diff --git a/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.js b/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.js new file mode 100644 index 0000000000..8f3f16b17c --- /dev/null +++ b/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.js @@ -0,0 +1,295 @@ +//// [tests/cases/compiler/incrementalConcurrentSafeAliasFollowing.ts] //// + +//// [a.tsbuildinfo] +{ + "version": "TEST", + "root": [ [ 8, 9 ] ], + "fileNames": [ + "lib.d.ts", + "lib.es5.d.ts", + "lib.dom.d.ts", + "lib.webworker.importscripts.d.ts", + "lib.scripthost.d.ts", + "lib.decorators.d.ts", + "lib.decorators.legacy.d.ts", + "./.src/file2.ts", + "./.src/file1.ts" + ], + "fileInfos": [ + "8aa2344ef67b04dfd9aa23b0f29ffb31", + { + "version": "71cf8049ea8d435bcdf47408dac2525c", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "9cf691967d2e0b0210f5864fdf1ad87a", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "eb49c11101339d745cfc83e213607152", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "a4fa81fccf6300a830a36517b5beb51f", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "45c91c5f844a9ee1df11d1b71c484b0e", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "39e009135c77d60baa790854b51d2195", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + "ed441e10e1833cd4635f7c61645b7ee7", + "553372ff8498789eb6e91ea68f08e47a" + ], + "fileIdsList": [ [ 8 ] ], + "options": { + "newLine": 1, + "noErrorTruncation": true, + "skipDefaultLibCheck": true, + "tsBuildInfoFile": "./a.tsbuildinfo" + }, + "referencedMap": [ [ 9, 1 ] ] +} +//// [file1.ts] +// need an out of date but present buildinfo, chained export aliases, +// and enough files that the same checker is used for multiple files +// to trigger the race from typescript-go/#1470 +import {b} from "./file2.js" + +export type {b as c} +//// [file2.ts] +const a = 1 + +export type {a as b} +//// [file0.ts] +import {c} from "./file1.js" + +export type {c as d} +//// [file3.ts] +import {b} from "./file2.js" + +export type {b as e} +//// [file4.ts] +import {b} from "./file2.js" + +export type {b as f} +//// [file5.ts] +import {b} from "./file2.js" + +export type {b as g} +//// [file6.ts] +import {b} from "./file2.js" + +export type {b as h} +//// [file7.ts] +import {b} from "./file2.js" + +export type {b as i} +//// [file8.ts] +import {b} from "./file2.js" + +export type {b as j} +//// [file9.ts] +import {b} from "./file2.js" + +export type {b as k} +//// [file10.ts] +import {b} from "./file2.js" + +export type {b as l} +//// [file11.ts] +import {b} from "./file2.js" + +export type {b as m} +//// [file12.ts] +import {b} from "./file2.js" + +export type {b as n} +//// [file13.ts] +import {b} from "./file2.js" + +export type {b as o} +//// [file14.ts] +import {b} from "./file2.js" + +export type {b as p} +//// [file15.ts] +import {b} from "./file2.js" + +export type {b as q} +//// [barrel.ts] +export * from "./file0.js" +export * from "./file1.js" +export * from "./file2.js" +export * from "./file3.js" +export * from "./file4.js" +export * from "./file5.js" +export * from "./file6.js" +export * from "./file7.js" +export * from "./file8.js" +export * from "./file9.js" +export * from "./file10.js" +export * from "./file11.js" +export * from "./file12.js" +export * from "./file13.js" +export * from "./file14.js" +export * from "./file15.js" + +//// [file2.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const a = 1; +//// [file1.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file0.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file3.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file4.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file5.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file6.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file7.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file8.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file9.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file10.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file11.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file12.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file13.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file14.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [file15.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [barrel.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./file0.js"), exports); +__exportStar(require("./file1.js"), exports); +__exportStar(require("./file2.js"), exports); +__exportStar(require("./file3.js"), exports); +__exportStar(require("./file4.js"), exports); +__exportStar(require("./file5.js"), exports); +__exportStar(require("./file6.js"), exports); +__exportStar(require("./file7.js"), exports); +__exportStar(require("./file8.js"), exports); +__exportStar(require("./file9.js"), exports); +__exportStar(require("./file10.js"), exports); +__exportStar(require("./file11.js"), exports); +__exportStar(require("./file12.js"), exports); +__exportStar(require("./file13.js"), exports); +__exportStar(require("./file14.js"), exports); +__exportStar(require("./file15.js"), exports); + + +//// [file2.d.ts] +declare const a = 1; +export type { a as b }; +//// [file1.d.ts] +import { b } from "./file2.js"; +export type { b as c }; +//// [file0.d.ts] +import { c } from "./file1.js"; +export type { c as d }; +//// [file3.d.ts] +import { b } from "./file2.js"; +export type { b as e }; +//// [file4.d.ts] +import { b } from "./file2.js"; +export type { b as f }; +//// [file5.d.ts] +import { b } from "./file2.js"; +export type { b as g }; +//// [file6.d.ts] +import { b } from "./file2.js"; +export type { b as h }; +//// [file7.d.ts] +import { b } from "./file2.js"; +export type { b as i }; +//// [file8.d.ts] +import { b } from "./file2.js"; +export type { b as j }; +//// [file9.d.ts] +import { b } from "./file2.js"; +export type { b as k }; +//// [file10.d.ts] +import { b } from "./file2.js"; +export type { b as l }; +//// [file11.d.ts] +import { b } from "./file2.js"; +export type { b as m }; +//// [file12.d.ts] +import { b } from "./file2.js"; +export type { b as n }; +//// [file13.d.ts] +import { b } from "./file2.js"; +export type { b as o }; +//// [file14.d.ts] +import { b } from "./file2.js"; +export type { b as p }; +//// [file15.d.ts] +import { b } from "./file2.js"; +export type { b as q }; +//// [barrel.d.ts] +export * from "./file0.js"; +export * from "./file1.js"; +export * from "./file2.js"; +export * from "./file3.js"; +export * from "./file4.js"; +export * from "./file5.js"; +export * from "./file6.js"; +export * from "./file7.js"; +export * from "./file8.js"; +export * from "./file9.js"; +export * from "./file10.js"; +export * from "./file11.js"; +export * from "./file12.js"; +export * from "./file13.js"; +export * from "./file14.js"; +export * from "./file15.js"; diff --git a/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.symbols b/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.symbols new file mode 100644 index 0000000000..b6ca4ff7d0 --- /dev/null +++ b/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.symbols @@ -0,0 +1,151 @@ +//// [tests/cases/compiler/incrementalConcurrentSafeAliasFollowing.ts] //// + +=== file1.ts === +// need an out of date but present buildinfo, chained export aliases, +// and enough files that the same checker is used for multiple files +// to trigger the race from typescript-go/#1470 +import {b} from "./file2.js" +>b : Symbol(b, Decl(file1.ts, 3, 8)) + +export type {b as c} +>b : Symbol(b, Decl(file1.ts, 3, 8)) +>c : Symbol(c, Decl(file1.ts, 5, 13)) + +=== file2.ts === +const a = 1 +>a : Symbol(a, Decl(file2.ts, 0, 5)) + +export type {a as b} +>a : Symbol(a, Decl(file2.ts, 0, 5)) +>b : Symbol(b, Decl(file2.ts, 2, 13)) + +=== file0.ts === +import {c} from "./file1.js" +>c : Symbol(c, Decl(file0.ts, 0, 8)) + +export type {c as d} +>c : Symbol(c, Decl(file0.ts, 0, 8)) +>d : Symbol(d, Decl(file0.ts, 2, 13)) + +=== file3.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file3.ts, 0, 8)) + +export type {b as e} +>b : Symbol(b, Decl(file3.ts, 0, 8)) +>e : Symbol(e, Decl(file3.ts, 2, 13)) + +=== file4.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file4.ts, 0, 8)) + +export type {b as f} +>b : Symbol(b, Decl(file4.ts, 0, 8)) +>f : Symbol(f, Decl(file4.ts, 2, 13)) + +=== file5.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file5.ts, 0, 8)) + +export type {b as g} +>b : Symbol(b, Decl(file5.ts, 0, 8)) +>g : Symbol(g, Decl(file5.ts, 2, 13)) + +=== file6.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file6.ts, 0, 8)) + +export type {b as h} +>b : Symbol(b, Decl(file6.ts, 0, 8)) +>h : Symbol(h, Decl(file6.ts, 2, 13)) + +=== file7.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file7.ts, 0, 8)) + +export type {b as i} +>b : Symbol(b, Decl(file7.ts, 0, 8)) +>i : Symbol(i, Decl(file7.ts, 2, 13)) + +=== file8.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file8.ts, 0, 8)) + +export type {b as j} +>b : Symbol(b, Decl(file8.ts, 0, 8)) +>j : Symbol(j, Decl(file8.ts, 2, 13)) + +=== file9.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file9.ts, 0, 8)) + +export type {b as k} +>b : Symbol(b, Decl(file9.ts, 0, 8)) +>k : Symbol(k, Decl(file9.ts, 2, 13)) + +=== file10.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file10.ts, 0, 8)) + +export type {b as l} +>b : Symbol(b, Decl(file10.ts, 0, 8)) +>l : Symbol(l, Decl(file10.ts, 2, 13)) + +=== file11.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file11.ts, 0, 8)) + +export type {b as m} +>b : Symbol(b, Decl(file11.ts, 0, 8)) +>m : Symbol(m, Decl(file11.ts, 2, 13)) + +=== file12.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file12.ts, 0, 8)) + +export type {b as n} +>b : Symbol(b, Decl(file12.ts, 0, 8)) +>n : Symbol(n, Decl(file12.ts, 2, 13)) + +=== file13.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file13.ts, 0, 8)) + +export type {b as o} +>b : Symbol(b, Decl(file13.ts, 0, 8)) +>o : Symbol(o, Decl(file13.ts, 2, 13)) + +=== file14.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file14.ts, 0, 8)) + +export type {b as p} +>b : Symbol(b, Decl(file14.ts, 0, 8)) +>p : Symbol(p, Decl(file14.ts, 2, 13)) + +=== file15.ts === +import {b} from "./file2.js" +>b : Symbol(b, Decl(file15.ts, 0, 8)) + +export type {b as q} +>b : Symbol(b, Decl(file15.ts, 0, 8)) +>q : Symbol(q, Decl(file15.ts, 2, 13)) + +=== barrel.ts === + +export * from "./file0.js" +export * from "./file1.js" +export * from "./file2.js" +export * from "./file3.js" +export * from "./file4.js" +export * from "./file5.js" +export * from "./file6.js" +export * from "./file7.js" +export * from "./file8.js" +export * from "./file9.js" +export * from "./file10.js" +export * from "./file11.js" +export * from "./file12.js" +export * from "./file13.js" +export * from "./file14.js" +export * from "./file15.js" diff --git a/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.types b/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.types new file mode 100644 index 0000000000..b2b0234037 --- /dev/null +++ b/testdata/baselines/reference/compiler/incrementalConcurrentSafeAliasFollowing.types @@ -0,0 +1,152 @@ +//// [tests/cases/compiler/incrementalConcurrentSafeAliasFollowing.ts] //// + +=== file1.ts === +// need an out of date but present buildinfo, chained export aliases, +// and enough files that the same checker is used for multiple files +// to trigger the race from typescript-go/#1470 +import {b} from "./file2.js" +>b : 1 + +export type {b as c} +>b : 1 +>c : any + +=== file2.ts === +const a = 1 +>a : 1 +>1 : 1 + +export type {a as b} +>a : 1 +>b : any + +=== file0.ts === +import {c} from "./file1.js" +>c : 1 + +export type {c as d} +>c : 1 +>d : any + +=== file3.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as e} +>b : 1 +>e : any + +=== file4.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as f} +>b : 1 +>f : any + +=== file5.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as g} +>b : 1 +>g : any + +=== file6.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as h} +>b : 1 +>h : any + +=== file7.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as i} +>b : 1 +>i : any + +=== file8.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as j} +>b : 1 +>j : any + +=== file9.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as k} +>b : 1 +>k : any + +=== file10.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as l} +>b : 1 +>l : any + +=== file11.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as m} +>b : 1 +>m : any + +=== file12.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as n} +>b : 1 +>n : any + +=== file13.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as o} +>b : 1 +>o : any + +=== file14.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as p} +>b : 1 +>p : any + +=== file15.ts === +import {b} from "./file2.js" +>b : 1 + +export type {b as q} +>b : 1 +>q : any + +=== barrel.ts === + +export * from "./file0.js" +export * from "./file1.js" +export * from "./file2.js" +export * from "./file3.js" +export * from "./file4.js" +export * from "./file5.js" +export * from "./file6.js" +export * from "./file7.js" +export * from "./file8.js" +export * from "./file9.js" +export * from "./file10.js" +export * from "./file11.js" +export * from "./file12.js" +export * from "./file13.js" +export * from "./file14.js" +export * from "./file15.js" diff --git a/testdata/tests/cases/compiler/incrementalConcurrentSafeAliasFollowing.ts b/testdata/tests/cases/compiler/incrementalConcurrentSafeAliasFollowing.ts new file mode 100644 index 0000000000..4d0f8a3e22 --- /dev/null +++ b/testdata/tests/cases/compiler/incrementalConcurrentSafeAliasFollowing.ts @@ -0,0 +1,147 @@ +// @incremental: true +// @outDir: ./res +// @declaration: true +// @tsBuildInfoFile: /a.tsbuildinfo +// @filename: /a.tsbuildinfo +{ + "version": "TEST", + "root": [ [ 8, 9 ] ], + "fileNames": [ + "lib.d.ts", + "lib.es5.d.ts", + "lib.dom.d.ts", + "lib.webworker.importscripts.d.ts", + "lib.scripthost.d.ts", + "lib.decorators.d.ts", + "lib.decorators.legacy.d.ts", + "./.src/file2.ts", + "./.src/file1.ts" + ], + "fileInfos": [ + "8aa2344ef67b04dfd9aa23b0f29ffb31", + { + "version": "71cf8049ea8d435bcdf47408dac2525c", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "9cf691967d2e0b0210f5864fdf1ad87a", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "eb49c11101339d745cfc83e213607152", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "a4fa81fccf6300a830a36517b5beb51f", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "45c91c5f844a9ee1df11d1b71c484b0e", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + { + "version": "39e009135c77d60baa790854b51d2195", + "affectsGlobalScope": true, + "impliedNodeFormat": 1 + }, + "ed441e10e1833cd4635f7c61645b7ee7", + "553372ff8498789eb6e91ea68f08e47a" + ], + "fileIdsList": [ [ 8 ] ], + "options": { + "newLine": 1, + "noErrorTruncation": true, + "skipDefaultLibCheck": true, + "tsBuildInfoFile": "./a.tsbuildinfo" + }, + "referencedMap": [ [ 9, 1 ] ] +} +// @filename: file1.ts +// need an out of date but present buildinfo, chained export aliases, +// and enough files that the same checker is used for multiple files +// to trigger the race from typescript-go/#1470 +import {b} from "./file2.js" + +export type {b as c} +// @filename: file2.ts +const a = 1 + +export type {a as b} +// @filename: file0.ts +import {c} from "./file1.js" + +export type {c as d} +// @filename: file3.ts +import {b} from "./file2.js" + +export type {b as e} +// @filename: file4.ts +import {b} from "./file2.js" + +export type {b as f} +// @filename: file5.ts +import {b} from "./file2.js" + +export type {b as g} +// @filename: file6.ts +import {b} from "./file2.js" + +export type {b as h} +// @filename: file7.ts +import {b} from "./file2.js" + +export type {b as i} +// @filename: file8.ts +import {b} from "./file2.js" + +export type {b as j} +// @filename: file9.ts +import {b} from "./file2.js" + +export type {b as k} +// @filename: file10.ts +import {b} from "./file2.js" + +export type {b as l} +// @filename: file11.ts +import {b} from "./file2.js" + +export type {b as m} +// @filename: file12.ts +import {b} from "./file2.js" + +export type {b as n} +// @filename: file13.ts +import {b} from "./file2.js" + +export type {b as o} +// @filename: file14.ts +import {b} from "./file2.js" + +export type {b as p} +// @filename: file15.ts +import {b} from "./file2.js" + +export type {b as q} +// @filename: barrel.ts +export * from "./file0.js" +export * from "./file1.js" +export * from "./file2.js" +export * from "./file3.js" +export * from "./file4.js" +export * from "./file5.js" +export * from "./file6.js" +export * from "./file7.js" +export * from "./file8.js" +export * from "./file9.js" +export * from "./file10.js" +export * from "./file11.js" +export * from "./file12.js" +export * from "./file13.js" +export * from "./file14.js" +export * from "./file15.js" \ No newline at end of file From 8034f94a5d23dd1d477bab11a94047847e73e0e3 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Nov 2025 11:09:44 -0800 Subject: [PATCH 3/6] Remove unused LS impl, move base program fetch logic to interface --- internal/compiler/program.go | 5 +++++ internal/execute/incremental/program.go | 6 ++++++ internal/project/checkerpool.go | 14 +------------- internal/testrunner/compiler_runner.go | 14 +------------- .../testutil/tsbaseline/type_symbol_baseline.go | 9 +-------- 5 files changed, 14 insertions(+), 34 deletions(-) diff --git a/internal/compiler/program.go b/internal/compiler/program.go index 59641bfa75..9bd9c5db5a 100644 --- a/internal/compiler/program.go +++ b/internal/compiler/program.go @@ -1279,6 +1279,10 @@ func (p *Program) InstantiationCount() int { return count } +func (p *Program) Program() *Program { + return p +} + func (p *Program) GetSourceFileMetaData(path tspath.Path) ast.SourceFileMetaData { return p.sourceFileMetaDatas[path] } @@ -1457,6 +1461,7 @@ type ProgramLike interface { Emit(ctx context.Context, options EmitOptions) *EmitResult CommonSourceDirectory() string IsSourceFileDefaultLibrary(path tspath.Path) bool + Program() *Program } func HandleNoEmitOnError(ctx context.Context, program ProgramLike, file *ast.SourceFile) *EmitResult { diff --git a/internal/execute/incremental/program.go b/internal/execute/incremental/program.go index e91e889bbb..dd94d16241 100644 --- a/internal/execute/incremental/program.go +++ b/internal/execute/incremental/program.go @@ -90,6 +90,12 @@ func (p *Program) CommonSourceDirectory() string { return p.program.CommonSourceDirectory() } +// Program implements compiler.AnyProgram interface. +func (p *Program) Program() *compiler.Program { + p.panicIfNoProgram("Program") + return p.program +} + // IsSourceFileDefaultLibrary implements compiler.AnyProgram interface. func (p *Program) IsSourceFileDefaultLibrary(path tspath.Path) bool { p.panicIfNoProgram("IsSourceFileDefaultLibrary") diff --git a/internal/project/checkerpool.go b/internal/project/checkerpool.go index 92e51e8829..3618917d96 100644 --- a/internal/project/checkerpool.go +++ b/internal/project/checkerpool.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "iter" - "slices" "sync" "github.com/microsoft/typescript-go/internal/ast" @@ -81,18 +80,7 @@ func (p *CheckerPool) GetCheckerForFile(ctx context.Context, file *ast.SourceFil // GetCheckerForFileExclusive is the same as GetCheckerForFile but also locks a mutex associated with the checker. // Call `done` to free the lock. func (p *CheckerPool) GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { - c, done := p.GetCheckerForFile(ctx, file) - p.mu.Lock() - defer p.mu.Unlock() - - idx := slices.Index(p.checkers, c) - p.locks[idx].Lock() - return c, sync.OnceFunc(func() { - done() - p.mu.Lock() - defer p.mu.Unlock() - p.locks[idx].Unlock() - }) + panic("unimplemented") // implement if used by LS } func (p *CheckerPool) GetChecker(ctx context.Context) (*checker.Checker, func()) { diff --git a/internal/testrunner/compiler_runner.go b/internal/testrunner/compiler_runner.go index 8f2789382c..3a2745d242 100644 --- a/internal/testrunner/compiler_runner.go +++ b/internal/testrunner/compiler_runner.go @@ -12,9 +12,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/checker" - "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" - "github.com/microsoft/typescript-go/internal/execute/incremental" "github.com/microsoft/typescript-go/internal/repo" "github.com/microsoft/typescript-go/internal/testutil" "github.com/microsoft/typescript-go/internal/testutil/baseline" @@ -530,17 +528,7 @@ func createHarnessTestFile(unit *testUnit, currentDirectory string) *harnessutil func (c *compilerTest) verifyUnionOrdering(t *testing.T) { t.Run("union ordering", func(t *testing.T) { - var p *compiler.Program - switch desugared := c.result.Program.(type) { - case *compiler.Program: - { - p = desugared - } - case *incremental.Program: - { - p = desugared.GetProgram() - } - } + p := c.result.Program.Program() checkers, done := p.GetTypeCheckers(t.Context()) defer done() for _, c := range checkers { diff --git a/internal/testutil/tsbaseline/type_symbol_baseline.go b/internal/testutil/tsbaseline/type_symbol_baseline.go index d2efcf862f..b55d91dc10 100644 --- a/internal/testutil/tsbaseline/type_symbol_baseline.go +++ b/internal/testutil/tsbaseline/type_symbol_baseline.go @@ -12,7 +12,6 @@ import ( "github.com/microsoft/typescript-go/internal/checker" "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" - "github.com/microsoft/typescript-go/internal/execute/incremental" "github.com/microsoft/typescript-go/internal/nodebuilder" "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/scanner" @@ -277,13 +276,7 @@ func newTypeWriterWalker(program compiler.ProgramLike, hadErrorBaseline bool) *t func (walker *typeWriterWalker) getTypeCheckerForCurrentFile() (*checker.Checker, func()) { // If we don't use the right checker for the file, its contents won't be up to date // since the types/symbols baselines appear to depend on files having been checked. - switch p := walker.program.(type) { - case *compiler.Program: - return p.GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) - case *incremental.Program: - return p.GetProgram().GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) - } - panic("unknown program kind, cannot get checker for file") + return walker.program.Program().GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) } type typeWriterResult struct { From 8bbe4113df993a489e9cb145c15e1dd05940662b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Nov 2025 11:12:36 -0800 Subject: [PATCH 4/6] Speculatively lock other incremental checker usage w/o test --- internal/execute/incremental/programtosnapshot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/execute/incremental/programtosnapshot.go b/internal/execute/incremental/programtosnapshot.go index dfaeb25131..56e0415a94 100644 --- a/internal/execute/incremental/programtosnapshot.go +++ b/internal/execute/incremental/programtosnapshot.go @@ -263,7 +263,7 @@ func getReferencedFiles(program *compiler.Program, file *ast.SourceFile) *collec // We need to use a set here since the code can contain the same import twice, // but that will only be one dependency. // To avoid invernal conversion, the key of the referencedFiles map must be of type Path - checker, done := program.GetTypeCheckerForFile(context.TODO(), file) + checker, done := program.GetTypeCheckerForFileExclusive(context.TODO(), file) defer done() for _, importName := range file.Imports() { addReferencedFilesFromImportLiteral(file, &referencedFiles, checker, importName) From b42a8b51a4523e3b05bf19b09bf0835b7e8c6d44 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Nov 2025 11:28:44 -0800 Subject: [PATCH 5/6] Rename method --- internal/compiler/checkerpool.go | 6 +++--- internal/compiler/emitHost.go | 2 +- internal/compiler/program.go | 8 ++++---- internal/ls/api.go | 4 ++-- internal/ls/completions.go | 6 +++--- internal/ls/definition.go | 4 ++-- internal/ls/hover.go | 2 +- internal/ls/inlay_hints.go | 2 +- internal/ls/signaturehelp.go | 2 +- internal/ls/string_completions.go | 2 +- internal/project/checkerpool.go | 2 +- internal/testutil/tsbaseline/type_symbol_baseline.go | 2 +- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/internal/compiler/checkerpool.go b/internal/compiler/checkerpool.go index 9e0fe4e0cb..04d1fcafc5 100644 --- a/internal/compiler/checkerpool.go +++ b/internal/compiler/checkerpool.go @@ -13,7 +13,7 @@ import ( type CheckerPool interface { GetChecker(ctx context.Context) (*checker.Checker, func()) - GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) + GetCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) GetAllCheckers(ctx context.Context) ([]*checker.Checker, func()) Files(checker *checker.Checker) iter.Seq[*ast.SourceFile] @@ -42,14 +42,14 @@ func newCheckerPool(checkerCount int, program *Program) *checkerPool { return pool } -func (p *checkerPool) GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { +func (p *checkerPool) GetCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { p.createCheckers() checker := p.fileAssociations[file] return checker, noop } func (p *checkerPool) GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { - c, done := p.GetCheckerForFile(ctx, file) + c, done := p.GetCheckerForFileNonexclusive(ctx, file) idx := slices.Index(p.checkers, c) p.locks[idx].Lock() return c, sync.OnceFunc(func() { diff --git a/internal/compiler/emitHost.go b/internal/compiler/emitHost.go index fcc0406342..3ad6bcebe3 100644 --- a/internal/compiler/emitHost.go +++ b/internal/compiler/emitHost.go @@ -35,7 +35,7 @@ type emitHost struct { } func newEmitHost(ctx context.Context, program *Program, file *ast.SourceFile) (*emitHost, func()) { - checker, done := program.GetTypeCheckerForFile(ctx, file) + checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) return &emitHost{ program: program, emitResolver: checker.GetEmitResolver(), diff --git a/internal/compiler/program.go b/internal/compiler/program.go index 9bd9c5db5a..fe2110b36d 100644 --- a/internal/compiler/program.go +++ b/internal/compiler/program.go @@ -379,8 +379,8 @@ func (p *Program) GetTypeCheckers(ctx context.Context) ([]*checker.Checker, func // method returns the checker that was tasked with checking the file. Note that it isn't possible to mix // types obtained from different checkers, so only non-type data (such as diagnostics or string // representations of types) should be obtained from checkers returned by this method. -func (p *Program) GetTypeCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { - return p.checkerPool.GetCheckerForFile(ctx, file) +func (p *Program) GetTypeCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { + return p.checkerPool.GetCheckerForFileNonexclusive(ctx, file) } // Return a checker for the given file, locked to the current thread to prevent data races from multiple threads @@ -1029,7 +1029,7 @@ func (p *Program) getSemanticDiagnosticsForFileNotFilter(ctx context.Context, so var fileChecker *checker.Checker var done func() if sourceFile != nil { - fileChecker, done = p.checkerPool.GetCheckerForFile(ctx, sourceFile) + fileChecker, done = p.checkerPool.GetCheckerForFileNonexclusive(ctx, sourceFile) defer done() } diags := slices.Clip(sourceFile.BindDiagnostics()) @@ -1134,7 +1134,7 @@ func (p *Program) getSuggestionDiagnosticsForFile(ctx context.Context, sourceFil var fileChecker *checker.Checker var done func() if sourceFile != nil { - fileChecker, done = p.checkerPool.GetCheckerForFile(ctx, sourceFile) + fileChecker, done = p.checkerPool.GetCheckerForFileNonexclusive(ctx, sourceFile) defer done() } diff --git a/internal/ls/api.go b/internal/ls/api.go index 4393806e72..54b377f4f9 100644 --- a/internal/ls/api.go +++ b/internal/ls/api.go @@ -24,14 +24,14 @@ func (l *LanguageService) GetSymbolAtPosition(ctx context.Context, fileName stri if node == nil { return nil, fmt.Errorf("%w: %s:%d", ErrNoTokenAtPosition, fileName, position) } - checker, done := program.GetTypeCheckerForFile(ctx, file) + checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) defer done() return checker.GetSymbolAtLocation(node), nil } func (l *LanguageService) GetSymbolAtLocation(ctx context.Context, node *ast.Node) *ast.Symbol { program := l.GetProgram() - checker, done := program.GetTypeCheckerForFile(ctx, ast.GetSourceFileOfNode(node)) + checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, ast.GetSourceFileOfNode(node)) defer done() return checker.GetSymbolAtLocation(node) } diff --git a/internal/ls/completions.go b/internal/ls/completions.go index 8d37b93b94..87a8732b9b 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -388,7 +388,7 @@ func (l *LanguageService) getCompletionsAtPosition( ) } - checker, done := l.GetProgram().GetTypeCheckerForFile(ctx, file) + checker, done := l.GetProgram().GetTypeCheckerForFileNonexclusive(ctx, file) defer done() preferences := l.UserPreferences() data := l.getCompletionData(ctx, checker, file, position, preferences) @@ -1941,7 +1941,7 @@ func (l *LanguageService) getCompletionEntriesFromSymbols( ) (uniqueNames collections.Set[string], sortedEntries []*lsproto.CompletionItem) { closestSymbolDeclaration := getClosestSymbolDeclaration(data.contextToken, data.location) useSemicolons := lsutil.ProbablyUsesSemicolons(file) - typeChecker, done := l.GetProgram().GetTypeCheckerForFile(ctx, file) + typeChecker, done := l.GetProgram().GetTypeCheckerForFileNonexclusive(ctx, file) defer done() isMemberCompletion := isMemberCompletionKind(data.completionKind) // Tracks unique names. @@ -5056,7 +5056,7 @@ func (l *LanguageService) getCompletionItemDetails( itemData *CompletionItemData, clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionItem { - checker, done := program.GetTypeCheckerForFile(ctx, file) + checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) defer done() docFormat := getCompletionDocumentationFormat(clientOptions) contextToken, previousToken := getRelevantTokens(position, file) diff --git a/internal/ls/definition.go b/internal/ls/definition.go index 9f0d231fc7..e3038888e1 100644 --- a/internal/ls/definition.go +++ b/internal/ls/definition.go @@ -26,7 +26,7 @@ func (l *LanguageService) ProvideDefinition( } originSelectionRange := l.createLspRangeFromNode(node, file) - c, done := program.GetTypeCheckerForFile(ctx, file) + c, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) defer done() if node.Kind == ast.KindOverrideKeyword { @@ -77,7 +77,7 @@ func (l *LanguageService) ProvideTypeDefinition( } originSelectionRange := l.createLspRangeFromNode(node, file) - c, done := program.GetTypeCheckerForFile(ctx, file) + c, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) defer done() node = getDeclarationNameForKeyword(node) diff --git a/internal/ls/hover.go b/internal/ls/hover.go index 002de77956..2ca3f07139 100644 --- a/internal/ls/hover.go +++ b/internal/ls/hover.go @@ -25,7 +25,7 @@ func (l *LanguageService) ProvideHover(ctx context.Context, documentURI lsproto. // Avoid giving quickInfo for the sourceFile as a whole. return lsproto.HoverOrNull{}, nil } - c, done := program.GetTypeCheckerForFile(ctx, file) + c, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) defer done() rangeNode := getNodeForQuickInfo(node) quickInfo, documentation := l.getQuickInfoAndDocumentationForSymbol(c, c.GetSymbolAtLocation(node), rangeNode, contentFormat) diff --git a/internal/ls/inlay_hints.go b/internal/ls/inlay_hints.go index 9ac0ddc574..fd021dbb06 100644 --- a/internal/ls/inlay_hints.go +++ b/internal/ls/inlay_hints.go @@ -31,7 +31,7 @@ func (l *LanguageService) ProvideInlayHint( program, file := l.getProgramAndFile(params.TextDocument.Uri) quotePreference := getQuotePreference(file, l.UserPreferences()) - checker, done := program.GetTypeCheckerForFile(ctx, file) + checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) defer done() inlayHintState := &inlayHintState{ ctx: ctx, diff --git a/internal/ls/signaturehelp.go b/internal/ls/signaturehelp.go index 7ce6e6c35f..3bef520585 100644 --- a/internal/ls/signaturehelp.go +++ b/internal/ls/signaturehelp.go @@ -67,7 +67,7 @@ func (l *LanguageService) GetSignatureHelpItems( clientOptions *lsproto.SignatureHelpClientCapabilities, docFormat lsproto.MarkupKind, ) *lsproto.SignatureHelp { - typeChecker, done := program.GetTypeCheckerForFile(ctx, sourceFile) + typeChecker, done := program.GetTypeCheckerForFileNonexclusive(ctx, sourceFile) defer done() // Decide whether to show signature help diff --git a/internal/ls/string_completions.go b/internal/ls/string_completions.go index cb34509554..e038a4c386 100644 --- a/internal/ls/string_completions.go +++ b/internal/ls/string_completions.go @@ -225,7 +225,7 @@ func (l *LanguageService) getStringLiteralCompletionEntries( node *ast.StringLiteralLike, position int, ) *stringLiteralCompletions { - typeChecker, done := l.GetProgram().GetTypeCheckerForFile(ctx, file) + typeChecker, done := l.GetProgram().GetTypeCheckerForFileNonexclusive(ctx, file) defer done() parent := walkUpParentheses(node.Parent) switch parent.Kind { diff --git a/internal/project/checkerpool.go b/internal/project/checkerpool.go index 3618917d96..056c488f72 100644 --- a/internal/project/checkerpool.go +++ b/internal/project/checkerpool.go @@ -44,7 +44,7 @@ func newCheckerPool(maxCheckers int, program *compiler.Program, log func(msg str return pool } -func (p *CheckerPool) GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { +func (p *CheckerPool) GetCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { p.mu.Lock() defer p.mu.Unlock() diff --git a/internal/testutil/tsbaseline/type_symbol_baseline.go b/internal/testutil/tsbaseline/type_symbol_baseline.go index b55d91dc10..92d8d1ed37 100644 --- a/internal/testutil/tsbaseline/type_symbol_baseline.go +++ b/internal/testutil/tsbaseline/type_symbol_baseline.go @@ -276,7 +276,7 @@ func newTypeWriterWalker(program compiler.ProgramLike, hadErrorBaseline bool) *t func (walker *typeWriterWalker) getTypeCheckerForCurrentFile() (*checker.Checker, func()) { // If we don't use the right checker for the file, its contents won't be up to date // since the types/symbols baselines appear to depend on files having been checked. - return walker.program.Program().GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) + return walker.program.Program().GetTypeCheckerForFileNonexclusive(context.Background(), walker.currentSourceFile) } type typeWriterResult struct { From 821a91c75a8b53499143f52ed6fd6407d2c70fbd Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Nov 2025 12:07:19 -0800 Subject: [PATCH 6/6] Revert "Rename method" This reverts commit b42a8b51a4523e3b05bf19b09bf0835b7e8c6d44. --- internal/compiler/checkerpool.go | 6 +++--- internal/compiler/emitHost.go | 2 +- internal/compiler/program.go | 8 ++++---- internal/ls/api.go | 4 ++-- internal/ls/completions.go | 6 +++--- internal/ls/definition.go | 4 ++-- internal/ls/hover.go | 2 +- internal/ls/inlay_hints.go | 2 +- internal/ls/signaturehelp.go | 2 +- internal/ls/string_completions.go | 2 +- internal/project/checkerpool.go | 2 +- internal/testutil/tsbaseline/type_symbol_baseline.go | 2 +- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/internal/compiler/checkerpool.go b/internal/compiler/checkerpool.go index 04d1fcafc5..9e0fe4e0cb 100644 --- a/internal/compiler/checkerpool.go +++ b/internal/compiler/checkerpool.go @@ -13,7 +13,7 @@ import ( type CheckerPool interface { GetChecker(ctx context.Context) (*checker.Checker, func()) - GetCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) + GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) GetAllCheckers(ctx context.Context) ([]*checker.Checker, func()) Files(checker *checker.Checker) iter.Seq[*ast.SourceFile] @@ -42,14 +42,14 @@ func newCheckerPool(checkerCount int, program *Program) *checkerPool { return pool } -func (p *checkerPool) GetCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { +func (p *checkerPool) GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { p.createCheckers() checker := p.fileAssociations[file] return checker, noop } func (p *checkerPool) GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { - c, done := p.GetCheckerForFileNonexclusive(ctx, file) + c, done := p.GetCheckerForFile(ctx, file) idx := slices.Index(p.checkers, c) p.locks[idx].Lock() return c, sync.OnceFunc(func() { diff --git a/internal/compiler/emitHost.go b/internal/compiler/emitHost.go index 3ad6bcebe3..fcc0406342 100644 --- a/internal/compiler/emitHost.go +++ b/internal/compiler/emitHost.go @@ -35,7 +35,7 @@ type emitHost struct { } func newEmitHost(ctx context.Context, program *Program, file *ast.SourceFile) (*emitHost, func()) { - checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) + checker, done := program.GetTypeCheckerForFile(ctx, file) return &emitHost{ program: program, emitResolver: checker.GetEmitResolver(), diff --git a/internal/compiler/program.go b/internal/compiler/program.go index fe2110b36d..9bd9c5db5a 100644 --- a/internal/compiler/program.go +++ b/internal/compiler/program.go @@ -379,8 +379,8 @@ func (p *Program) GetTypeCheckers(ctx context.Context) ([]*checker.Checker, func // method returns the checker that was tasked with checking the file. Note that it isn't possible to mix // types obtained from different checkers, so only non-type data (such as diagnostics or string // representations of types) should be obtained from checkers returned by this method. -func (p *Program) GetTypeCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { - return p.checkerPool.GetCheckerForFileNonexclusive(ctx, file) +func (p *Program) GetTypeCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { + return p.checkerPool.GetCheckerForFile(ctx, file) } // Return a checker for the given file, locked to the current thread to prevent data races from multiple threads @@ -1029,7 +1029,7 @@ func (p *Program) getSemanticDiagnosticsForFileNotFilter(ctx context.Context, so var fileChecker *checker.Checker var done func() if sourceFile != nil { - fileChecker, done = p.checkerPool.GetCheckerForFileNonexclusive(ctx, sourceFile) + fileChecker, done = p.checkerPool.GetCheckerForFile(ctx, sourceFile) defer done() } diags := slices.Clip(sourceFile.BindDiagnostics()) @@ -1134,7 +1134,7 @@ func (p *Program) getSuggestionDiagnosticsForFile(ctx context.Context, sourceFil var fileChecker *checker.Checker var done func() if sourceFile != nil { - fileChecker, done = p.checkerPool.GetCheckerForFileNonexclusive(ctx, sourceFile) + fileChecker, done = p.checkerPool.GetCheckerForFile(ctx, sourceFile) defer done() } diff --git a/internal/ls/api.go b/internal/ls/api.go index 54b377f4f9..4393806e72 100644 --- a/internal/ls/api.go +++ b/internal/ls/api.go @@ -24,14 +24,14 @@ func (l *LanguageService) GetSymbolAtPosition(ctx context.Context, fileName stri if node == nil { return nil, fmt.Errorf("%w: %s:%d", ErrNoTokenAtPosition, fileName, position) } - checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) + checker, done := program.GetTypeCheckerForFile(ctx, file) defer done() return checker.GetSymbolAtLocation(node), nil } func (l *LanguageService) GetSymbolAtLocation(ctx context.Context, node *ast.Node) *ast.Symbol { program := l.GetProgram() - checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, ast.GetSourceFileOfNode(node)) + checker, done := program.GetTypeCheckerForFile(ctx, ast.GetSourceFileOfNode(node)) defer done() return checker.GetSymbolAtLocation(node) } diff --git a/internal/ls/completions.go b/internal/ls/completions.go index 87a8732b9b..8d37b93b94 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -388,7 +388,7 @@ func (l *LanguageService) getCompletionsAtPosition( ) } - checker, done := l.GetProgram().GetTypeCheckerForFileNonexclusive(ctx, file) + checker, done := l.GetProgram().GetTypeCheckerForFile(ctx, file) defer done() preferences := l.UserPreferences() data := l.getCompletionData(ctx, checker, file, position, preferences) @@ -1941,7 +1941,7 @@ func (l *LanguageService) getCompletionEntriesFromSymbols( ) (uniqueNames collections.Set[string], sortedEntries []*lsproto.CompletionItem) { closestSymbolDeclaration := getClosestSymbolDeclaration(data.contextToken, data.location) useSemicolons := lsutil.ProbablyUsesSemicolons(file) - typeChecker, done := l.GetProgram().GetTypeCheckerForFileNonexclusive(ctx, file) + typeChecker, done := l.GetProgram().GetTypeCheckerForFile(ctx, file) defer done() isMemberCompletion := isMemberCompletionKind(data.completionKind) // Tracks unique names. @@ -5056,7 +5056,7 @@ func (l *LanguageService) getCompletionItemDetails( itemData *CompletionItemData, clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionItem { - checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) + checker, done := program.GetTypeCheckerForFile(ctx, file) defer done() docFormat := getCompletionDocumentationFormat(clientOptions) contextToken, previousToken := getRelevantTokens(position, file) diff --git a/internal/ls/definition.go b/internal/ls/definition.go index e3038888e1..9f0d231fc7 100644 --- a/internal/ls/definition.go +++ b/internal/ls/definition.go @@ -26,7 +26,7 @@ func (l *LanguageService) ProvideDefinition( } originSelectionRange := l.createLspRangeFromNode(node, file) - c, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) + c, done := program.GetTypeCheckerForFile(ctx, file) defer done() if node.Kind == ast.KindOverrideKeyword { @@ -77,7 +77,7 @@ func (l *LanguageService) ProvideTypeDefinition( } originSelectionRange := l.createLspRangeFromNode(node, file) - c, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) + c, done := program.GetTypeCheckerForFile(ctx, file) defer done() node = getDeclarationNameForKeyword(node) diff --git a/internal/ls/hover.go b/internal/ls/hover.go index 2ca3f07139..002de77956 100644 --- a/internal/ls/hover.go +++ b/internal/ls/hover.go @@ -25,7 +25,7 @@ func (l *LanguageService) ProvideHover(ctx context.Context, documentURI lsproto. // Avoid giving quickInfo for the sourceFile as a whole. return lsproto.HoverOrNull{}, nil } - c, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) + c, done := program.GetTypeCheckerForFile(ctx, file) defer done() rangeNode := getNodeForQuickInfo(node) quickInfo, documentation := l.getQuickInfoAndDocumentationForSymbol(c, c.GetSymbolAtLocation(node), rangeNode, contentFormat) diff --git a/internal/ls/inlay_hints.go b/internal/ls/inlay_hints.go index fd021dbb06..9ac0ddc574 100644 --- a/internal/ls/inlay_hints.go +++ b/internal/ls/inlay_hints.go @@ -31,7 +31,7 @@ func (l *LanguageService) ProvideInlayHint( program, file := l.getProgramAndFile(params.TextDocument.Uri) quotePreference := getQuotePreference(file, l.UserPreferences()) - checker, done := program.GetTypeCheckerForFileNonexclusive(ctx, file) + checker, done := program.GetTypeCheckerForFile(ctx, file) defer done() inlayHintState := &inlayHintState{ ctx: ctx, diff --git a/internal/ls/signaturehelp.go b/internal/ls/signaturehelp.go index 3bef520585..7ce6e6c35f 100644 --- a/internal/ls/signaturehelp.go +++ b/internal/ls/signaturehelp.go @@ -67,7 +67,7 @@ func (l *LanguageService) GetSignatureHelpItems( clientOptions *lsproto.SignatureHelpClientCapabilities, docFormat lsproto.MarkupKind, ) *lsproto.SignatureHelp { - typeChecker, done := program.GetTypeCheckerForFileNonexclusive(ctx, sourceFile) + typeChecker, done := program.GetTypeCheckerForFile(ctx, sourceFile) defer done() // Decide whether to show signature help diff --git a/internal/ls/string_completions.go b/internal/ls/string_completions.go index e038a4c386..cb34509554 100644 --- a/internal/ls/string_completions.go +++ b/internal/ls/string_completions.go @@ -225,7 +225,7 @@ func (l *LanguageService) getStringLiteralCompletionEntries( node *ast.StringLiteralLike, position int, ) *stringLiteralCompletions { - typeChecker, done := l.GetProgram().GetTypeCheckerForFileNonexclusive(ctx, file) + typeChecker, done := l.GetProgram().GetTypeCheckerForFile(ctx, file) defer done() parent := walkUpParentheses(node.Parent) switch parent.Kind { diff --git a/internal/project/checkerpool.go b/internal/project/checkerpool.go index 056c488f72..3618917d96 100644 --- a/internal/project/checkerpool.go +++ b/internal/project/checkerpool.go @@ -44,7 +44,7 @@ func newCheckerPool(maxCheckers int, program *compiler.Program, log func(msg str return pool } -func (p *CheckerPool) GetCheckerForFileNonexclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { +func (p *CheckerPool) GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func()) { p.mu.Lock() defer p.mu.Unlock() diff --git a/internal/testutil/tsbaseline/type_symbol_baseline.go b/internal/testutil/tsbaseline/type_symbol_baseline.go index 92d8d1ed37..b55d91dc10 100644 --- a/internal/testutil/tsbaseline/type_symbol_baseline.go +++ b/internal/testutil/tsbaseline/type_symbol_baseline.go @@ -276,7 +276,7 @@ func newTypeWriterWalker(program compiler.ProgramLike, hadErrorBaseline bool) *t func (walker *typeWriterWalker) getTypeCheckerForCurrentFile() (*checker.Checker, func()) { // If we don't use the right checker for the file, its contents won't be up to date // since the types/symbols baselines appear to depend on files having been checked. - return walker.program.Program().GetTypeCheckerForFileNonexclusive(context.Background(), walker.currentSourceFile) + return walker.program.Program().GetTypeCheckerForFile(context.Background(), walker.currentSourceFile) } type typeWriterResult struct {