ttsc 0.28.4 → 0.28.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/ttsc/api_compile.go +6 -4
- package/cmd/ttsc/api_transform.go +6 -4
- package/cmd/ttsc/build.go +7 -6
- package/cmd/ttscgraph/serve.go +70 -77
- package/cmd/ttscgraph/serve_session_reloads_superseding_module_candidates_test.go +26 -0
- package/cmd/ttscgraph/serve_session_tracks_all_module_specifier_forms_test.go +1 -2
- package/driver/graph.go +67 -35
- package/driver/input_observation.go +305 -115
- package/driver/input_observation_test.go +203 -0
- package/driver/program.go +28 -4
- package/driver/resolution_candidates.go +247 -741
- package/driver/resolution_candidates_test.go +341 -0
- package/lib/compiler/internal/project/readProjectConfig.js +9 -7
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
- package/lib/compiler/internal/runBuild.js +1 -0
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/sharedHostHelpers.d.ts +4 -0
- package/lib/compiler/internal/sharedHostHelpers.js +11 -1
- package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
- package/lib/compiler/internal/startResidentTransform.js +1 -0
- package/lib/compiler/internal/startResidentTransform.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +165 -8
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/internal/projectInputPathIdentity.js +8 -7
- package/lib/internal/projectInputPathIdentity.js.map +1 -1
- package/lib/structures/ITtscCompilerTransformation.d.ts +57 -19
- package/package.json +8 -8
- package/shim/compiler/incremental.go +52 -0
- package/shim/compiler/resolution.go +444 -0
- package/shim/core/shim.go +15 -1
- package/src/compiler/internal/project/readProjectConfig.ts +9 -7
- package/src/compiler/internal/runBuild.ts +2 -0
- package/src/compiler/internal/sharedHostHelpers.ts +14 -0
- package/src/compiler/internal/startResidentTransform.ts +2 -0
- package/src/compiler/internal/transformProjectInMemory.ts +193 -8
- package/src/internal/projectInputPathIdentity.ts +8 -7
- package/src/structures/ITtscCompilerTransformation.ts +65 -19
- package/utility/host.go +8 -7
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
// gen_shims:hand-maintained
|
|
2
|
+
|
|
3
|
+
package compiler
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"strings"
|
|
7
|
+
"time"
|
|
8
|
+
|
|
9
|
+
"github.com/microsoft/typescript-go/internal/ast"
|
|
10
|
+
"github.com/microsoft/typescript-go/internal/collections"
|
|
11
|
+
"github.com/microsoft/typescript-go/internal/core"
|
|
12
|
+
"github.com/microsoft/typescript-go/internal/module"
|
|
13
|
+
"github.com/microsoft/typescript-go/internal/symlinks"
|
|
14
|
+
"github.com/microsoft/typescript-go/internal/tsoptions"
|
|
15
|
+
"github.com/microsoft/typescript-go/internal/tspath"
|
|
16
|
+
"github.com/microsoft/typescript-go/internal/vfs"
|
|
17
|
+
"github.com/microsoft/typescript-go/internal/vfs/cachedvfs"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
// ProgramResolutionKind distinguishes module and type-reference resolution.
|
|
21
|
+
type ProgramResolutionKind uint8
|
|
22
|
+
|
|
23
|
+
const (
|
|
24
|
+
ProgramResolutionKindModule ProgramResolutionKind = iota
|
|
25
|
+
ProgramResolutionKindTypeReference
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
// ProgramResolutionTask is one resolution already performed by a resident
|
|
29
|
+
// Program. The exported fields provide deterministic host ordering while the
|
|
30
|
+
// unexported fields retain the exact compiler context needed for replay.
|
|
31
|
+
type ProgramResolutionTask struct {
|
|
32
|
+
ContainingFile string
|
|
33
|
+
Kind ProgramResolutionKind
|
|
34
|
+
Mode core.ResolutionMode
|
|
35
|
+
Name string
|
|
36
|
+
ResolvedFile string
|
|
37
|
+
SourceFile string
|
|
38
|
+
TargetFile string
|
|
39
|
+
Universal bool
|
|
40
|
+
|
|
41
|
+
compilerOptions *core.CompilerOptions
|
|
42
|
+
currentDirectory string
|
|
43
|
+
expected programResolutionResult
|
|
44
|
+
projectReferences *projectReferenceResolutionContext
|
|
45
|
+
redirectedReference module.ResolvedProjectReference
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ProgramResolutionTasks returns every cached module and type-reference
|
|
49
|
+
// resolution, including unresolved entries and automatic type directives.
|
|
50
|
+
func ProgramResolutionTasks(program *Program) []ProgramResolutionTask {
|
|
51
|
+
if program == nil {
|
|
52
|
+
return nil
|
|
53
|
+
}
|
|
54
|
+
projectReferences := newProjectReferenceResolutionContext(program)
|
|
55
|
+
tasks := []ProgramResolutionTask{}
|
|
56
|
+
appendTask := func(kind ProgramResolutionKind, name string, mode core.ResolutionMode, filePath tspath.Path, expected programResolutionResult) {
|
|
57
|
+
containingFile := string(filePath)
|
|
58
|
+
sourceFile := ""
|
|
59
|
+
targetFile := ""
|
|
60
|
+
var redirectedReference module.ResolvedProjectReference
|
|
61
|
+
if source := program.GetSourceFileByPath(filePath); source != nil {
|
|
62
|
+
sourceFile = source.FileName()
|
|
63
|
+
redirectedReference, containingFile = programResolutionContext(program, source)
|
|
64
|
+
}
|
|
65
|
+
if target := program.GetSourceFileForResolvedModule(expected.resolvedFileName); target != nil {
|
|
66
|
+
targetFile = target.FileName()
|
|
67
|
+
}
|
|
68
|
+
tasks = append(tasks, ProgramResolutionTask{
|
|
69
|
+
ContainingFile: containingFile,
|
|
70
|
+
Kind: kind,
|
|
71
|
+
Mode: mode,
|
|
72
|
+
Name: name,
|
|
73
|
+
ResolvedFile: expected.resolvedFileName,
|
|
74
|
+
SourceFile: sourceFile,
|
|
75
|
+
TargetFile: targetFile,
|
|
76
|
+
Universal: strings.HasSuffix(containingFile, module.InferredTypesContainingFile),
|
|
77
|
+
compilerOptions: program.Options(),
|
|
78
|
+
currentDirectory: program.GetCurrentDirectory(),
|
|
79
|
+
expected: expected,
|
|
80
|
+
projectReferences: projectReferences,
|
|
81
|
+
redirectedReference: redirectedReference,
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
program.ForEachResolvedModule(func(resolution *module.ResolvedModule, name string, mode core.ResolutionMode, filePath tspath.Path) {
|
|
85
|
+
appendTask(ProgramResolutionKindModule, name, mode, filePath, moduleResolutionResult(resolution))
|
|
86
|
+
}, nil)
|
|
87
|
+
program.ForEachResolvedTypeReferenceDirective(func(resolution *module.ResolvedTypeReferenceDirective, name string, mode core.ResolutionMode, filePath tspath.Path) {
|
|
88
|
+
appendTask(ProgramResolutionKindTypeReference, name, mode, filePath, typeReferenceResolutionResult(resolution))
|
|
89
|
+
}, nil)
|
|
90
|
+
return tasks
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// programResolutionContext mirrors projectReferenceFileMapper's containing
|
|
94
|
+
// file substitution using the public Program maps. The selected source path is
|
|
95
|
+
// part of resolution semantics, not merely diagnostic provenance.
|
|
96
|
+
func programResolutionContext(program *Program, source ast.HasFileName) (module.ResolvedProjectReference, string) {
|
|
97
|
+
if redirected := program.GetProjectReferenceFromSource(source.Path()); redirected != nil {
|
|
98
|
+
return redirected.Resolved, redirected.Source
|
|
99
|
+
}
|
|
100
|
+
if redirected := program.GetProjectReferenceFromOutputDts(source.Path()); redirected != nil {
|
|
101
|
+
return redirected.Resolved, redirected.Source
|
|
102
|
+
}
|
|
103
|
+
redirect := program.GetRedirectForResolution(source)
|
|
104
|
+
if redirect == nil {
|
|
105
|
+
return nil, source.FileName()
|
|
106
|
+
}
|
|
107
|
+
// The remaining redirect form is a preserved node_modules symlink whose
|
|
108
|
+
// physical declaration belongs to a project reference. Resolve the same
|
|
109
|
+
// physical key the compiler mapper used and retain the original source name.
|
|
110
|
+
realpath := program.Host().FS().Realpath(source.FileName())
|
|
111
|
+
path := tspath.ToPath(realpath, program.GetCurrentDirectory(), program.UseCaseSensitiveFileNames())
|
|
112
|
+
if redirected := program.GetProjectReferenceFromOutputDts(path); redirected != nil {
|
|
113
|
+
return redirected.Resolved, redirected.Source
|
|
114
|
+
}
|
|
115
|
+
// A concurrent retarget can make the public lookup disappear after the
|
|
116
|
+
// resident redirect was cached. Keep the redirect so replay necessarily
|
|
117
|
+
// disagrees with the resident result or its observed identity proof fails.
|
|
118
|
+
return redirect, source.FileName()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ReplayProgramResolutions resolves one source's tasks with one fresh upstream
|
|
122
|
+
// resolver and reports whether every result still matches the resident Program.
|
|
123
|
+
func ReplayProgramResolutions(tasks []ProgramResolutionTask, filesystem vfs.FS) bool {
|
|
124
|
+
if len(tasks) == 0 || filesystem == nil || tasks[0].compilerOptions == nil {
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
first := tasks[0]
|
|
128
|
+
host := resolutionHost{
|
|
129
|
+
filesystem: first.projectReferences.filesystem(filesystem),
|
|
130
|
+
currentDirectory: first.currentDirectory,
|
|
131
|
+
}
|
|
132
|
+
resolver := module.NewResolver(host, first.compilerOptions, "", "")
|
|
133
|
+
matches := true
|
|
134
|
+
for _, task := range tasks {
|
|
135
|
+
var actual programResolutionResult
|
|
136
|
+
switch task.Kind {
|
|
137
|
+
case ProgramResolutionKindModule:
|
|
138
|
+
resolution, _ := resolver.ResolveModuleName(task.Name, task.ContainingFile, task.Mode, task.redirectedReference)
|
|
139
|
+
actual = moduleResolutionResult(resolution)
|
|
140
|
+
case ProgramResolutionKindTypeReference:
|
|
141
|
+
resolution, _ := resolver.ResolveTypeReferenceDirective(task.Name, task.ContainingFile, task.Mode, task.redirectedReference)
|
|
142
|
+
actual = typeReferenceResolutionResult(resolution)
|
|
143
|
+
default:
|
|
144
|
+
matches = false
|
|
145
|
+
continue
|
|
146
|
+
}
|
|
147
|
+
if actual != task.expected {
|
|
148
|
+
matches = false
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return matches
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// projectReferenceResolutionContext snapshots the immutable metadata needed to
|
|
155
|
+
// recreate fileLoader's project-reference declaration view for every replay
|
|
156
|
+
// filesystem. A referenced output declaration may be absent on disk while its
|
|
157
|
+
// source exists; the resolver must see the virtual declaration before Program
|
|
158
|
+
// substitutes that source into the loaded graph.
|
|
159
|
+
type projectReferenceResolutionContext struct {
|
|
160
|
+
currentDirectory string
|
|
161
|
+
dtsDirectories collections.Set[tspath.Path]
|
|
162
|
+
outputDtsToProjectReference map[tspath.Path]*tsoptions.SourceOutputAndProjectReference
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
func newProjectReferenceResolutionContext(program *Program) *projectReferenceResolutionContext {
|
|
166
|
+
if program == nil {
|
|
167
|
+
return nil
|
|
168
|
+
}
|
|
169
|
+
outputDtsToProjectReference := map[tspath.Path]*tsoptions.SourceOutputAndProjectReference{}
|
|
170
|
+
dtsDirectories := collections.Set[tspath.Path]{}
|
|
171
|
+
useSourceOfProjectReference := false
|
|
172
|
+
program.RangeResolvedProjectReference(func(_ tspath.Path, config *tsoptions.ParsedCommandLine, _ *tsoptions.ParsedCommandLine, _ int) bool {
|
|
173
|
+
if config == nil {
|
|
174
|
+
return true
|
|
175
|
+
}
|
|
176
|
+
config.ParseInputOutputNames()
|
|
177
|
+
for path := range config.SourceToProjectReference() {
|
|
178
|
+
useSourceOfProjectReference = useSourceOfProjectReference || program.IsSourceFromProjectReference(path)
|
|
179
|
+
}
|
|
180
|
+
for path, reference := range config.OutputDtsToProjectReference() {
|
|
181
|
+
outputDtsToProjectReference[path] = reference
|
|
182
|
+
}
|
|
183
|
+
declarationDirectory := config.CompilerOptions().DeclarationDir
|
|
184
|
+
if declarationDirectory == "" {
|
|
185
|
+
declarationDirectory = config.CompilerOptions().OutDir
|
|
186
|
+
}
|
|
187
|
+
if declarationDirectory != "" {
|
|
188
|
+
dtsDirectories.Add(tspath.ToPath(declarationDirectory, program.GetCurrentDirectory(), program.UseCaseSensitiveFileNames()))
|
|
189
|
+
}
|
|
190
|
+
return true
|
|
191
|
+
})
|
|
192
|
+
if !useSourceOfProjectReference || len(outputDtsToProjectReference) == 0 {
|
|
193
|
+
return nil
|
|
194
|
+
}
|
|
195
|
+
return &projectReferenceResolutionContext{
|
|
196
|
+
currentDirectory: program.GetCurrentDirectory(),
|
|
197
|
+
dtsDirectories: dtsDirectories,
|
|
198
|
+
outputDtsToProjectReference: outputDtsToProjectReference,
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
func (context *projectReferenceResolutionContext) filesystem(filesystem vfs.FS) vfs.FS {
|
|
203
|
+
if context == nil || filesystem == nil {
|
|
204
|
+
return filesystem
|
|
205
|
+
}
|
|
206
|
+
return cachedvfs.From(&projectReferenceResolutionFS{
|
|
207
|
+
filesystem: filesystem,
|
|
208
|
+
currentDirectory: context.currentDirectory,
|
|
209
|
+
dtsDirectories: context.dtsDirectories,
|
|
210
|
+
knownSymlinks: symlinks.KnownSymlinks{},
|
|
211
|
+
outputDtsToProjectReference: context.outputDtsToProjectReference,
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// projectReferenceResolutionFS mirrors TypeScript-Go's
|
|
216
|
+
// projectReferenceDtsFakingVfs over the caller's observation filesystem.
|
|
217
|
+
type projectReferenceResolutionFS struct {
|
|
218
|
+
filesystem vfs.FS
|
|
219
|
+
currentDirectory string
|
|
220
|
+
dtsDirectories collections.Set[tspath.Path]
|
|
221
|
+
knownSymlinks symlinks.KnownSymlinks
|
|
222
|
+
outputDtsToProjectReference map[tspath.Path]*tsoptions.SourceOutputAndProjectReference
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
var _ vfs.FS = (*projectReferenceResolutionFS)(nil)
|
|
226
|
+
|
|
227
|
+
func (fs *projectReferenceResolutionFS) UseCaseSensitiveFileNames() bool {
|
|
228
|
+
return fs.filesystem.UseCaseSensitiveFileNames()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
func (fs *projectReferenceResolutionFS) FileExists(path string) bool {
|
|
232
|
+
if fs.filesystem.FileExists(path) {
|
|
233
|
+
return true
|
|
234
|
+
}
|
|
235
|
+
if !tspath.IsDeclarationFileName(path) {
|
|
236
|
+
return false
|
|
237
|
+
}
|
|
238
|
+
return fs.fileOrDirectoryExistsUsingSource(path, true)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
func (fs *projectReferenceResolutionFS) ReadFile(path string) (string, bool) {
|
|
242
|
+
return fs.filesystem.ReadFile(path)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
func (fs *projectReferenceResolutionFS) WriteFile(string, string) error {
|
|
246
|
+
panic("should not be called by resolver")
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
func (fs *projectReferenceResolutionFS) AppendFile(string, string) error {
|
|
250
|
+
panic("should not be called by resolver")
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
func (fs *projectReferenceResolutionFS) Remove(string) error {
|
|
254
|
+
panic("should not be called by resolver")
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
func (fs *projectReferenceResolutionFS) Chtimes(string, time.Time, time.Time) error {
|
|
258
|
+
panic("should not be called by resolver")
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
func (fs *projectReferenceResolutionFS) DirectoryExists(path string) bool {
|
|
262
|
+
if fs.filesystem.DirectoryExists(path) {
|
|
263
|
+
fs.handleDirectoryCouldBeSymlink(path)
|
|
264
|
+
return true
|
|
265
|
+
}
|
|
266
|
+
return fs.fileOrDirectoryExistsUsingSource(path, false)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
func (fs *projectReferenceResolutionFS) GetAccessibleEntries(string) vfs.Entries {
|
|
270
|
+
panic("should not be called by resolver")
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
func (fs *projectReferenceResolutionFS) Stat(string) vfs.FileInfo {
|
|
274
|
+
panic("should not be called by resolver")
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
func (fs *projectReferenceResolutionFS) WalkDir(string, vfs.WalkDirFunc) error {
|
|
278
|
+
panic("should not be called by resolver")
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
func (fs *projectReferenceResolutionFS) Realpath(path string) string {
|
|
282
|
+
if result, ok := fs.knownSymlinks.Files().Load(fs.toPath(path)); ok {
|
|
283
|
+
return result
|
|
284
|
+
}
|
|
285
|
+
return fs.filesystem.Realpath(path)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
func (fs *projectReferenceResolutionFS) toPath(path string) tspath.Path {
|
|
289
|
+
return tspath.ToPath(path, fs.currentDirectory, fs.UseCaseSensitiveFileNames())
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
func (fs *projectReferenceResolutionFS) handleDirectoryCouldBeSymlink(directory string) {
|
|
293
|
+
if tspath.ContainsIgnoredPath(directory) || !strings.Contains(directory, "/node_modules/") {
|
|
294
|
+
return
|
|
295
|
+
}
|
|
296
|
+
directoryPath := tspath.Path(tspath.EnsureTrailingDirectorySeparator(string(fs.toPath(directory))))
|
|
297
|
+
if _, ok := fs.knownSymlinks.Directories().Load(directoryPath); ok {
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
realDirectory := fs.Realpath(directory)
|
|
301
|
+
if realDirectory == directory {
|
|
302
|
+
return
|
|
303
|
+
}
|
|
304
|
+
realPath := tspath.Path(tspath.EnsureTrailingDirectorySeparator(string(fs.toPath(realDirectory))))
|
|
305
|
+
if realPath == directoryPath {
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
fs.knownSymlinks.SetDirectory(directory, directoryPath, &symlinks.KnownDirectoryLink{
|
|
309
|
+
Real: tspath.EnsureTrailingDirectorySeparator(realDirectory),
|
|
310
|
+
RealPath: realPath,
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
func (fs *projectReferenceResolutionFS) fileOrDirectoryExistsUsingSource(fileOrDirectory string, isFile bool) bool {
|
|
315
|
+
existence := fs.directoryExistsIfProjectReferenceDeclarationDirectory
|
|
316
|
+
if isFile {
|
|
317
|
+
existence = fs.fileExistsIfProjectReferenceDeclaration
|
|
318
|
+
}
|
|
319
|
+
result := existence(fileOrDirectory)
|
|
320
|
+
if result != core.TSUnknown {
|
|
321
|
+
return result == core.TSTrue
|
|
322
|
+
}
|
|
323
|
+
knownDirectoryLinks := fs.knownSymlinks.Directories()
|
|
324
|
+
if knownDirectoryLinks.Size() == 0 {
|
|
325
|
+
return false
|
|
326
|
+
}
|
|
327
|
+
fileOrDirectoryPath := fs.toPath(fileOrDirectory)
|
|
328
|
+
if !strings.Contains(string(fileOrDirectoryPath), "/node_modules/") {
|
|
329
|
+
return false
|
|
330
|
+
}
|
|
331
|
+
if isFile {
|
|
332
|
+
if _, ok := fs.knownSymlinks.Files().Load(fileOrDirectoryPath); ok {
|
|
333
|
+
return true
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
exists := false
|
|
337
|
+
knownDirectoryLinks.Range(func(directoryPath tspath.Path, knownDirectoryLink *symlinks.KnownDirectoryLink) bool {
|
|
338
|
+
relative, hasPrefix := strings.CutPrefix(string(fileOrDirectoryPath), string(directoryPath))
|
|
339
|
+
if !hasPrefix {
|
|
340
|
+
return true
|
|
341
|
+
}
|
|
342
|
+
if exists = existence(string(knownDirectoryLink.RealPath) + relative).IsTrue(); !exists {
|
|
343
|
+
return true
|
|
344
|
+
}
|
|
345
|
+
if isFile {
|
|
346
|
+
absolutePath := tspath.GetNormalizedAbsolutePath(fileOrDirectory, fs.currentDirectory)
|
|
347
|
+
fs.knownSymlinks.SetFile(
|
|
348
|
+
absolutePath,
|
|
349
|
+
fileOrDirectoryPath,
|
|
350
|
+
knownDirectoryLink.Real+absolutePath[len(directoryPath):],
|
|
351
|
+
)
|
|
352
|
+
}
|
|
353
|
+
return false
|
|
354
|
+
})
|
|
355
|
+
return exists
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
func (fs *projectReferenceResolutionFS) fileExistsIfProjectReferenceDeclaration(file string) core.Tristate {
|
|
359
|
+
reference := fs.outputDtsToProjectReference[fs.toPath(file)]
|
|
360
|
+
if reference == nil {
|
|
361
|
+
return core.TSUnknown
|
|
362
|
+
}
|
|
363
|
+
return core.IfElse(fs.filesystem.FileExists(reference.Source), core.TSTrue, core.TSFalse)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
func (fs *projectReferenceResolutionFS) directoryExistsIfProjectReferenceDeclarationDirectory(directory string) core.Tristate {
|
|
367
|
+
directoryPath := fs.toPath(directory)
|
|
368
|
+
directoryPathWithSeparator := directoryPath + "/"
|
|
369
|
+
for declarationDirectoryPath := range fs.dtsDirectories.Keys() {
|
|
370
|
+
if directoryPath == declarationDirectoryPath || strings.HasPrefix(string(declarationDirectoryPath), string(directoryPathWithSeparator)) || strings.HasPrefix(string(directoryPath), string(declarationDirectoryPath)+"/") {
|
|
371
|
+
return core.TSTrue
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return core.TSUnknown
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// ReplayAutomaticTypeDirectiveDiscovery repeats the compiler's exact wildcard
|
|
378
|
+
// type-root enumeration over filesystem so a host can observe its inputs.
|
|
379
|
+
func ReplayAutomaticTypeDirectiveDiscovery(program *Program, filesystem vfs.FS) {
|
|
380
|
+
if program == nil || filesystem == nil || program.Options() == nil {
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
module.GetAutomaticTypeDirectiveNames(program.Options(), resolutionHost{
|
|
384
|
+
filesystem: filesystem,
|
|
385
|
+
currentDirectory: program.GetCurrentDirectory(),
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
type resolutionHost struct {
|
|
390
|
+
filesystem vfs.FS
|
|
391
|
+
currentDirectory string
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
func (host resolutionHost) FS() vfs.FS { return host.filesystem }
|
|
395
|
+
|
|
396
|
+
func (host resolutionHost) GetCurrentDirectory() string { return host.currentDirectory }
|
|
397
|
+
|
|
398
|
+
type programResolutionResult struct {
|
|
399
|
+
alternateResult string
|
|
400
|
+
extension string
|
|
401
|
+
isExternalLibraryImport bool
|
|
402
|
+
originalPath string
|
|
403
|
+
packageName string
|
|
404
|
+
packagePeerDependencies string
|
|
405
|
+
packageSubModuleName string
|
|
406
|
+
packageVersion string
|
|
407
|
+
primary bool
|
|
408
|
+
resolvedFileName string
|
|
409
|
+
resolvedUsingTsExtension bool
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
func moduleResolutionResult(resolution *module.ResolvedModule) programResolutionResult {
|
|
413
|
+
if resolution == nil {
|
|
414
|
+
return programResolutionResult{}
|
|
415
|
+
}
|
|
416
|
+
return programResolutionResult{
|
|
417
|
+
alternateResult: resolution.AlternateResult,
|
|
418
|
+
extension: resolution.Extension,
|
|
419
|
+
isExternalLibraryImport: resolution.IsExternalLibraryImport,
|
|
420
|
+
originalPath: resolution.OriginalPath,
|
|
421
|
+
packageName: resolution.PackageId.Name,
|
|
422
|
+
packagePeerDependencies: resolution.PackageId.PeerDependencies,
|
|
423
|
+
packageSubModuleName: resolution.PackageId.SubModuleName,
|
|
424
|
+
packageVersion: resolution.PackageId.Version,
|
|
425
|
+
resolvedFileName: resolution.ResolvedFileName,
|
|
426
|
+
resolvedUsingTsExtension: resolution.ResolvedUsingTsExtension,
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
func typeReferenceResolutionResult(resolution *module.ResolvedTypeReferenceDirective) programResolutionResult {
|
|
431
|
+
if resolution == nil {
|
|
432
|
+
return programResolutionResult{}
|
|
433
|
+
}
|
|
434
|
+
return programResolutionResult{
|
|
435
|
+
isExternalLibraryImport: resolution.IsExternalLibraryImport,
|
|
436
|
+
originalPath: resolution.OriginalPath,
|
|
437
|
+
packageName: resolution.PackageId.Name,
|
|
438
|
+
packagePeerDependencies: resolution.PackageId.PeerDependencies,
|
|
439
|
+
packageSubModuleName: resolution.PackageId.SubModuleName,
|
|
440
|
+
packageVersion: resolution.PackageId.Version,
|
|
441
|
+
primary: resolution.Primary,
|
|
442
|
+
resolvedFileName: resolution.ResolvedFileName,
|
|
443
|
+
}
|
|
444
|
+
}
|
package/shim/core/shim.go
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
// primitives without exposing the full internal surface.
|
|
7
7
|
package core
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import (
|
|
10
|
+
innercore "github.com/microsoft/typescript-go/internal/core"
|
|
11
|
+
innersemver "github.com/microsoft/typescript-go/internal/semver"
|
|
12
|
+
)
|
|
10
13
|
|
|
11
14
|
// CompilerOptions holds the parsed tsconfig compiler options passed to the
|
|
12
15
|
// TypeScript-Go program host.
|
|
@@ -96,6 +99,17 @@ const (
|
|
|
96
99
|
// consumer can tell which checker resolved the facts it is reading.
|
|
97
100
|
func Version() string { return innercore.Version() }
|
|
98
101
|
|
|
102
|
+
// TypeScriptVersionSatisfiesRange reports whether the compiler's own version
|
|
103
|
+
// satisfies a typesVersions range under TypeScript-Go's semver grammar.
|
|
104
|
+
func TypeScriptVersionSatisfiesRange(text string) bool {
|
|
105
|
+
versionRange, ok := innersemver.TryParseVersionRange(text)
|
|
106
|
+
if !ok {
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
109
|
+
version, err := innersemver.TryParseVersion(innercore.Version())
|
|
110
|
+
return err == nil && versionRange.Test(&version)
|
|
111
|
+
}
|
|
112
|
+
|
|
99
113
|
// ComputeECMALineStarts applies the compiler's LF, CRLF, CR, LS, and PS line
|
|
100
114
|
// model to UTF-8 source text.
|
|
101
115
|
func ComputeECMALineStarts(text string) ECMALineStarts {
|
|
@@ -279,11 +279,12 @@ function resolveCompilerOptionPath(
|
|
|
279
279
|
configDir: string,
|
|
280
280
|
value: string,
|
|
281
281
|
): string {
|
|
282
|
+
const normalized = value.replaceAll("\\", "/");
|
|
282
283
|
if (
|
|
283
|
-
|
|
284
|
+
normalized.slice(0, CONFIG_DIR_TEMPLATE.length).toLowerCase() !==
|
|
284
285
|
CONFIG_DIR_TEMPLATE.toLowerCase()
|
|
285
286
|
) {
|
|
286
|
-
return resolveAbsolutePath(declaringDir,
|
|
287
|
+
return resolveAbsolutePath(declaringDir, normalized);
|
|
287
288
|
}
|
|
288
289
|
// The compiler picks the base directory from a case-insensitive prefix but
|
|
289
290
|
// substitutes only the exact spelling, so a mis-cased template still anchors
|
|
@@ -294,10 +295,10 @@ function resolveCompilerOptionPath(
|
|
|
294
295
|
// The exact spelling becomes "./" before the result is normalized, which
|
|
295
296
|
// keeps the value relative even when its remainder resembles an absolute
|
|
296
297
|
// Windows path. Either config-file separator is accepted on every host.
|
|
297
|
-
const substituted =
|
|
298
|
-
? `./${
|
|
299
|
-
:
|
|
300
|
-
return resolveAbsolutePath(configDir, substituted
|
|
298
|
+
const substituted = normalized.startsWith(CONFIG_DIR_TEMPLATE)
|
|
299
|
+
? `./${normalized.slice(CONFIG_DIR_TEMPLATE.length)}`
|
|
300
|
+
: normalized;
|
|
301
|
+
return resolveAbsolutePath(configDir, substituted);
|
|
301
302
|
}
|
|
302
303
|
|
|
303
304
|
/**
|
|
@@ -311,6 +312,7 @@ function resolveCompilerOptionPath(
|
|
|
311
312
|
* also tries appending `.json` when the first attempt fails).
|
|
312
313
|
*/
|
|
313
314
|
function resolveExtendsConfig(tsconfig: string, specifier: string): string {
|
|
315
|
+
specifier = specifier.replaceAll("\\", "/");
|
|
314
316
|
const baseDir = path.dirname(tsconfig);
|
|
315
317
|
if (path.isAbsolute(specifier)) {
|
|
316
318
|
return resolveExistingExtendsPath(specifier);
|
|
@@ -387,7 +389,7 @@ function resolvePackageManifestTsconfig(
|
|
|
387
389
|
if (typeof field !== "string" || field.length === 0) {
|
|
388
390
|
return undefined;
|
|
389
391
|
}
|
|
390
|
-
return path.resolve(path.dirname(manifestPath), field);
|
|
392
|
+
return path.resolve(path.dirname(manifestPath), field.replaceAll("\\", "/"));
|
|
391
393
|
}
|
|
392
394
|
|
|
393
395
|
/**
|
|
@@ -29,6 +29,7 @@ import { resolveTsgo } from "./resolveTsgo";
|
|
|
29
29
|
import {
|
|
30
30
|
TSGO_ARGS_ENV,
|
|
31
31
|
assertSharedHostCompatibility,
|
|
32
|
+
clearInheritedSemanticConfigPath,
|
|
32
33
|
clearInheritedTsgoArgs,
|
|
33
34
|
inheritedSidecarEnv,
|
|
34
35
|
linkedTransformPlugins,
|
|
@@ -230,6 +231,7 @@ function nativePluginEnv(
|
|
|
230
231
|
} else {
|
|
231
232
|
clearInheritedTsgoArgs(env, extra);
|
|
232
233
|
}
|
|
234
|
+
clearInheritedSemanticConfigPath(env, extra);
|
|
233
235
|
// The anchor is per-invocation state owned by this host: when this run
|
|
234
236
|
// declared none (and the caller's env does not name one), drop any value
|
|
235
237
|
// inherited from an ancestor ttsc process so a nested build never
|
|
@@ -9,6 +9,9 @@ import type { ITtscLoadedNativePlugin } from "../../structures/internal/ITtscLoa
|
|
|
9
9
|
*/
|
|
10
10
|
export const TSGO_ARGS_ENV = "TTSC_TSGO_ARGS";
|
|
11
11
|
|
|
12
|
+
/** Internal channel preserving a generated wrapper's user-authored config owner. */
|
|
13
|
+
export const SEMANTIC_CONFIG_PATH_ENV = "TTSC_SEMANTIC_CONFIG_PATH";
|
|
14
|
+
|
|
12
15
|
/**
|
|
13
16
|
* Drop a forwarded-tsgo payload this invocation did not publish itself.
|
|
14
17
|
*
|
|
@@ -29,6 +32,16 @@ export function clearInheritedTsgoArgs(
|
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
|
|
35
|
+
/** Drop an outer generated wrapper's config owner from an unrelated child run. */
|
|
36
|
+
export function clearInheritedSemanticConfigPath(
|
|
37
|
+
env: NodeJS.ProcessEnv,
|
|
38
|
+
callerEnv: NodeJS.ProcessEnv | undefined,
|
|
39
|
+
): void {
|
|
40
|
+
if (callerEnv?.[SEMANTIC_CONFIG_PATH_ENV] === undefined) {
|
|
41
|
+
delete env[SEMANTIC_CONFIG_PATH_ENV];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
32
45
|
/**
|
|
33
46
|
* The `{ ...process.env, ...callerEnv }` a child process inherits, minus a
|
|
34
47
|
* forwarded-tsgo payload this lane never published.
|
|
@@ -43,6 +56,7 @@ export function inheritedSidecarEnv(
|
|
|
43
56
|
): NodeJS.ProcessEnv {
|
|
44
57
|
const env: NodeJS.ProcessEnv = { ...process.env, ...callerEnv };
|
|
45
58
|
clearInheritedTsgoArgs(env, callerEnv);
|
|
59
|
+
clearInheritedSemanticConfigPath(env, callerEnv);
|
|
46
60
|
return env;
|
|
47
61
|
}
|
|
48
62
|
|
|
@@ -10,6 +10,7 @@ import { resolveBinary } from "./resolveBinary";
|
|
|
10
10
|
import { resolveTsgo } from "./resolveTsgo";
|
|
11
11
|
import {
|
|
12
12
|
assertSharedHostCompatibility,
|
|
13
|
+
clearInheritedSemanticConfigPath,
|
|
13
14
|
clearInheritedTsgoArgs,
|
|
14
15
|
inheritedSidecarEnv,
|
|
15
16
|
linkedTransformPlugins,
|
|
@@ -130,6 +131,7 @@ function residentEnv(
|
|
|
130
131
|
// This lane forwards no tsgo argv of its own, so anything inherited belongs
|
|
131
132
|
// to an outer ttsc run and must not reach the resident sidecar.
|
|
132
133
|
clearInheritedTsgoArgs(env, context.env);
|
|
134
|
+
clearInheritedSemanticConfigPath(env, context.env);
|
|
133
135
|
const linked = linkedTransformPlugins(nativePlugins);
|
|
134
136
|
if (linked.length !== 0) {
|
|
135
137
|
env.TTSC_LINKED_PLUGINS_JSON = serializeNativePlugins(linked);
|