@@ -5,35 +5,37 @@ import (
5
5
"iter"
6
6
"slices"
7
7
"strings"
8
- "sync"
8
+ "sync/atomic "
9
9
10
10
"github.com/microsoft/typescript-go/internal/ast"
11
+ "github.com/microsoft/typescript-go/internal/collections"
11
12
"github.com/microsoft/typescript-go/internal/compiler/module"
12
13
"github.com/microsoft/typescript-go/internal/core"
13
14
"github.com/microsoft/typescript-go/internal/tsoptions"
14
15
"github.com/microsoft/typescript-go/internal/tspath"
15
16
)
16
17
17
18
type fileLoader struct {
18
- host CompilerHost
19
- programOptions ProgramOptions
20
- compilerOptions * core.CompilerOptions
21
-
22
- resolver * module.Resolver
23
- resolvedModulesMutex sync.Mutex
24
- resolvedModules map [tspath.Path ]module.ModeAwareCache [* module.ResolvedModule ]
25
-
26
- sourceFileMetaDatasMutex sync.RWMutex
27
- sourceFileMetaDatas map [tspath.Path ]* ast.SourceFileMetaData
28
-
29
- mu sync.Mutex
30
- wg core.WorkGroup
31
- tasksByFileName map [string ]* parseTask
32
- currentNodeModulesDepth int
33
- defaultLibraryPath string
34
- comparePathsOptions tspath.ComparePathsOptions
35
- rootTasks []* parseTask
36
- supportedExtensions []string
19
+ host CompilerHost
20
+ programOptions ProgramOptions
21
+ compilerOptions * core.CompilerOptions
22
+ resolver * module.Resolver
23
+ defaultLibraryPath string
24
+ comparePathsOptions tspath.ComparePathsOptions
25
+ wg core.WorkGroup
26
+ supportedExtensions []string
27
+
28
+ tasksByFileName collections.SyncMap [string , * parseTask ]
29
+ rootTasks []* parseTask
30
+
31
+ totalFileCount atomic.Int32
32
+ libFileCount atomic.Int32
33
+ }
34
+
35
+ type processedFiles struct {
36
+ files []* ast.SourceFile
37
+ resolvedModules map [tspath.Path ]module.ModeAwareCache [* module.ResolvedModule ]
38
+ sourceFileMetaDatas map [tspath.Path ]* ast.SourceFileMetaData
37
39
}
38
40
39
41
func processAllProgramFiles (
@@ -43,14 +45,13 @@ func processAllProgramFiles(
43
45
resolver * module.Resolver ,
44
46
rootFiles []string ,
45
47
libs []string ,
46
- ) ( files [] * ast. SourceFile , resolvedModules map [tspath. Path ]module. ModeAwareCache [ * module. ResolvedModule ], sourceFileMetaDatas map [tspath. Path ] * ast. SourceFileMetaData ) {
48
+ ) processedFiles {
47
49
supportedExtensions := tsoptions .GetSupportedExtensions (compilerOptions , nil /*extraFileExtensions*/ )
48
50
loader := fileLoader {
49
51
host : host ,
50
52
programOptions : programOptions ,
51
53
compilerOptions : compilerOptions ,
52
54
resolver : resolver ,
53
- tasksByFileName : make (map [string ]* parseTask ),
54
55
defaultLibraryPath : tspath .GetNormalizedAbsolutePath (host .DefaultLibraryPath (), host .GetCurrentDirectory ()),
55
56
comparePathsOptions : tspath.ComparePathsOptions {
56
57
UseCaseSensitiveFileNames : host .FS ().UseCaseSensitiveFileNames (),
@@ -69,17 +70,35 @@ func processAllProgramFiles(
69
70
70
71
loader .wg .RunAndWait ()
71
72
72
- files , libFiles := []* ast.SourceFile {}, []* ast.SourceFile {}
73
+ totalFileCount := int (loader .totalFileCount .Load ())
74
+ libFileCount := int (loader .libFileCount .Load ())
75
+
76
+ files := make ([]* ast.SourceFile , 0 , totalFileCount - libFileCount )
77
+ libFiles := make ([]* ast.SourceFile , 0 , totalFileCount ) // totalFileCount here since we append files to it later to construct the final list
78
+
79
+ resolvedModules := make (map [tspath.Path ]module.ModeAwareCache [* module.ResolvedModule ], totalFileCount )
80
+ sourceFileMetaDatas := make (map [tspath.Path ]* ast.SourceFileMetaData , totalFileCount )
81
+
73
82
for task := range loader .collectTasks (loader .rootTasks ) {
83
+ file := task .file
74
84
if task .isLib {
75
- libFiles = append (libFiles , task . file )
85
+ libFiles = append (libFiles , file )
76
86
} else {
77
- files = append (files , task . file )
87
+ files = append (files , file )
78
88
}
89
+ path := file .Path ()
90
+ resolvedModules [path ] = task .resolutionsInFile
91
+ sourceFileMetaDatas [path ] = task .metadata
79
92
}
80
93
loader .sortLibs (libFiles )
81
94
82
- return append (libFiles , files ... ), loader .resolvedModules , loader .sourceFileMetaDatas
95
+ allFiles := append (libFiles , files ... )
96
+
97
+ return processedFiles {
98
+ files : allFiles ,
99
+ resolvedModules : resolvedModules ,
100
+ sourceFileMetaDatas : sourceFileMetaDatas ,
101
+ }
83
102
}
84
103
85
104
func (p * fileLoader ) addRootTasks (files []string , isLib bool ) {
@@ -111,42 +130,41 @@ func (p *fileLoader) addAutomaticTypeDirectiveTasks() {
111
130
112
131
func (p * fileLoader ) startTasks (tasks []* parseTask ) {
113
132
if len (tasks ) > 0 {
114
- p .mu .Lock ()
115
- defer p .mu .Unlock ()
116
133
for i , task := range tasks {
117
- // dedup tasks to ensure correct file order, regardless of which task would be started first
118
- if existingTask , ok := p .tasksByFileName [task .normalizedFilePath ]; ok {
119
- tasks [i ] = existingTask
134
+ loadedTask , loaded := p .tasksByFileName .LoadOrStore (task .normalizedFilePath , task )
135
+ if loaded {
136
+ // dedup tasks to ensure correct file order, regardless of which task would be started first
137
+ tasks [i ] = loadedTask
120
138
} else {
121
- p .tasksByFileName [task .normalizedFilePath ] = task
122
- task .start (p )
139
+ loadedTask .start (p )
123
140
}
124
141
}
125
142
}
126
143
}
127
144
128
145
func (p * fileLoader ) collectTasks (tasks []* parseTask ) iter.Seq [* parseTask ] {
129
146
return func (yield func (* parseTask ) bool ) {
130
- p .collectTasksWorker (tasks , yield )
147
+ p .collectTasksWorker (tasks , core. Set [ * parseTask ]{}, yield )
131
148
}
132
149
}
133
150
134
- func (p * fileLoader ) collectTasksWorker (tasks []* parseTask , yield func (* parseTask ) bool ) bool {
151
+ func (p * fileLoader ) collectTasksWorker (tasks []* parseTask , seen core. Set [ * parseTask ], yield func (* parseTask ) bool ) bool {
135
152
for _ , task := range tasks {
136
- if _ , ok := p .tasksByFileName [task .normalizedFilePath ]; ok {
137
- // ensure we only walk each task once
138
- delete (p .tasksByFileName , task .normalizedFilePath )
153
+ // ensure we only walk each task once
154
+ if seen .Has (task ) {
155
+ continue
156
+ }
157
+ seen .Add (task )
139
158
140
- if len (task .subTasks ) > 0 {
141
- if ! p .collectTasksWorker (task .subTasks , yield ) {
142
- return false
143
- }
159
+ if len (task .subTasks ) > 0 {
160
+ if ! p .collectTasksWorker (task .subTasks , seen , yield ) {
161
+ return false
144
162
}
163
+ }
145
164
146
- if task .file != nil {
147
- if ! yield (task ) {
148
- return false
149
- }
165
+ if task .file != nil {
166
+ if ! yield (task ) {
167
+ return false
150
168
}
151
169
}
152
170
}
@@ -184,11 +202,23 @@ type parseTask struct {
184
202
file * ast.SourceFile
185
203
isLib bool
186
204
subTasks []* parseTask
205
+
206
+ metadata * ast.SourceFileMetaData
207
+ resolutionsInFile module.ModeAwareCache [* module.ResolvedModule ]
187
208
}
188
209
189
210
func (t * parseTask ) start (loader * fileLoader ) {
211
+ loader .totalFileCount .Add (1 )
212
+ if t .isLib {
213
+ loader .libFileCount .Add (1 )
214
+ }
215
+
190
216
loader .wg .Queue (func () {
191
217
file := loader .parseSourceFile (t .normalizedFilePath )
218
+ t .file = file
219
+ loader .wg .Queue (func () {
220
+ t .metadata = loader .loadSourceFileMetaData (file .Path ())
221
+ })
192
222
193
223
// !!! if noResolve, skip all of this
194
224
t .subTasks = make ([]* parseTask , 0 , len (file .ReferencedFiles )+ len (file .Imports )+ len (file .ModuleAugmentations ))
@@ -215,42 +245,29 @@ func (t *parseTask) start(loader *fileLoader) {
215
245
}
216
246
}
217
247
218
- for _ , imp := range loader .resolveImportsAndModuleAugmentations (file ) {
248
+ importsAndAugmentations , resolutionsInFile := loader .resolveImportsAndModuleAugmentations (file )
249
+ for _ , imp := range importsAndAugmentations {
219
250
t .addSubTask (imp , false )
220
251
}
221
252
222
- t .file = file
253
+ t .resolutionsInFile = resolutionsInFile
254
+
223
255
loader .startTasks (t .subTasks )
224
256
})
225
257
}
226
258
227
- func (p * fileLoader ) loadSourceFileMetaData (path tspath.Path ) {
228
- p .sourceFileMetaDatasMutex .RLock ()
229
- _ , ok := p .sourceFileMetaDatas [path ]
230
- p .sourceFileMetaDatasMutex .RUnlock ()
231
- if ok {
232
- return
233
- }
234
-
259
+ func (p * fileLoader ) loadSourceFileMetaData (path tspath.Path ) * ast.SourceFileMetaData {
235
260
packageJsonType := p .resolver .GetPackageJsonTypeIfApplicable (string (path ))
236
261
impliedNodeFormat := ast .GetImpliedNodeFormatForFile (string (path ), packageJsonType )
237
- metadata := & ast.SourceFileMetaData {
262
+ return & ast.SourceFileMetaData {
238
263
PackageJsonType : packageJsonType ,
239
264
ImpliedNodeFormat : impliedNodeFormat ,
240
265
}
241
-
242
- p .sourceFileMetaDatasMutex .Lock ()
243
- defer p .sourceFileMetaDatasMutex .Unlock ()
244
- if p .sourceFileMetaDatas == nil {
245
- p .sourceFileMetaDatas = make (map [tspath.Path ]* ast.SourceFileMetaData )
246
- }
247
- p .sourceFileMetaDatas [path ] = metadata
248
266
}
249
267
250
268
func (p * fileLoader ) parseSourceFile (fileName string ) * ast.SourceFile {
251
269
path := tspath .ToPath (fileName , p .host .GetCurrentDirectory (), p .host .FS ().UseCaseSensitiveFileNames ())
252
270
sourceFile := p .host .GetSourceFile (fileName , path , p .compilerOptions .GetEmitScriptTarget ())
253
- p .loadSourceFileMetaData (path )
254
271
return sourceFile
255
272
}
256
273
@@ -269,21 +286,14 @@ func (p *fileLoader) resolveTripleslashPathReference(moduleName string, containi
269
286
return tspath .NormalizePath (referencedFileName )
270
287
}
271
288
272
- func (p * fileLoader ) resolveImportsAndModuleAugmentations (file * ast.SourceFile ) []string {
273
- toParse := make ([]string , 0 , len (file .Imports ))
289
+ func (p * fileLoader ) resolveImportsAndModuleAugmentations (file * ast.SourceFile ) ([]string , module.ModeAwareCache [* module.ResolvedModule ]) {
274
290
if len (file .Imports ) > 0 || len (file .ModuleAugmentations ) > 0 {
291
+ toParse := make ([]string , 0 , len (file .Imports ))
275
292
moduleNames := getModuleNames (file )
276
293
resolutions := p .resolveModuleNames (moduleNames , file )
277
294
278
295
resolutionsInFile := make (module.ModeAwareCache [* module.ResolvedModule ], len (resolutions ))
279
296
280
- p .resolvedModulesMutex .Lock ()
281
- defer p .resolvedModulesMutex .Unlock ()
282
- if p .resolvedModules == nil {
283
- p .resolvedModules = make (map [tspath.Path ]module.ModeAwareCache [* module.ResolvedModule ])
284
- }
285
- p .resolvedModules [file .Path ()] = resolutionsInFile
286
-
287
297
for i , resolution := range resolutions {
288
298
resolvedFileName := resolution .ResolvedFileName
289
299
// TODO(ercornel): !!!: check if from node modules
@@ -315,8 +325,10 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(file *ast.SourceFile)
315
325
toParse = append (toParse , resolvedFileName )
316
326
}
317
327
}
328
+
329
+ return toParse , resolutionsInFile
318
330
}
319
- return toParse
331
+ return nil , nil
320
332
}
321
333
322
334
func (p * fileLoader ) resolveModuleNames (entries []* ast.Node , file * ast.SourceFile ) []* module.ResolvedModule {
0 commit comments