Skip to content

Commit 3a82d57

Browse files
authored
Compute referencedBy when its needed (#1608)
1 parent 2230db5 commit 3a82d57

File tree

7 files changed

+69
-67
lines changed

7 files changed

+69
-67
lines changed

internal/collections/syncmanytomanyset.go

Lines changed: 0 additions & 34 deletions
This file was deleted.

internal/incremental/affectedfileshandler.go

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package incremental
22

33
import (
44
"context"
5-
"iter"
65
"maps"
76
"slices"
87
"sync"
@@ -139,23 +138,14 @@ func (h *affectedFilesHandler) getFilesAffectedBy(path tspath.Path) []*ast.Sourc
139138
})
140139
}
141140

142-
// Gets the files referenced by the the file path
143-
func (h *affectedFilesHandler) getReferencedByPaths(file tspath.Path) iter.Seq[tspath.Path] {
144-
keys, ok := h.program.snapshot.referencedMap.GetKeys(file)
145-
if !ok {
146-
return func(yield func(tspath.Path) bool) {}
147-
}
148-
return keys.Keys()
149-
}
150-
151141
func (h *affectedFilesHandler) forEachFileReferencedBy(file *ast.SourceFile, fn func(currentFile *ast.SourceFile, currentPath tspath.Path) (queueForFile bool, fastReturn bool)) map[tspath.Path]*ast.SourceFile {
152142
// Now we need to if each file in the referencedBy list has a shape change as well.
153143
// Because if so, its own referencedBy files need to be saved as well to make the
154144
// emitting result consistent with files on disk.
155145
seenFileNamesMap := map[tspath.Path]*ast.SourceFile{}
156146
// Start with the paths this file was referenced by
157147
seenFileNamesMap[file.Path()] = file
158-
queue := slices.Collect(h.getReferencedByPaths(file.Path()))
148+
queue := slices.Collect(h.program.snapshot.referencedMap.getReferencedBy(file.Path()))
159149
for len(queue) > 0 {
160150
currentPath := queue[len(queue)-1]
161151
queue = queue[:len(queue)-1]
@@ -167,7 +157,7 @@ func (h *affectedFilesHandler) forEachFileReferencedBy(file *ast.SourceFile, fn
167157
return seenFileNamesMap
168158
}
169159
if queueForFile {
170-
for ref := range h.getReferencedByPaths(currentFile.Path()) {
160+
for ref := range h.program.snapshot.referencedMap.getReferencedBy(currentFile.Path()) {
171161
queue = append(queue, ref)
172162
}
173163
}
@@ -253,18 +243,14 @@ func (h *affectedFilesHandler) handleDtsMayChangeOfAffectedFile(dtsMayChange dts
253243
}
254244

255245
// Go through files that reference affected file and handle dts emit and semantic diagnostics for them and their references
256-
if keys, ok := h.program.snapshot.referencedMap.GetKeys(affectedFile.Path()); ok {
257-
for exportedFromPath := range keys.Keys() {
258-
if h.handleDtsMayChangeOfGlobalScope(dtsMayChange, exportedFromPath, invalidateJsFiles) {
246+
for exportedFromPath := range h.program.snapshot.referencedMap.getReferencedBy(affectedFile.Path()) {
247+
if h.handleDtsMayChangeOfGlobalScope(dtsMayChange, exportedFromPath, invalidateJsFiles) {
248+
return
249+
}
250+
for filePath := range h.program.snapshot.referencedMap.getReferencedBy(exportedFromPath) {
251+
if h.handleDtsMayChangeOfFileAndExportsOfFile(dtsMayChange, filePath, invalidateJsFiles) {
259252
return
260253
}
261-
if references, ok := h.program.snapshot.referencedMap.GetKeys(exportedFromPath); ok {
262-
for filePath := range references.Keys() {
263-
if h.handleDtsMayChangeOfFileAndExportsOfFile(dtsMayChange, filePath, invalidateJsFiles) {
264-
return
265-
}
266-
}
267-
}
268254
}
269255
}
270256
}
@@ -279,11 +265,9 @@ func (h *affectedFilesHandler) handleDtsMayChangeOfFileAndExportsOfFile(dtsMayCh
279265
h.handleDtsMayChangeOf(dtsMayChange, filePath, invalidateJsFiles)
280266

281267
// Remove the diagnostics of files that import this file and handle all its exports too
282-
if keys, ok := h.program.snapshot.referencedMap.GetKeys(filePath); ok {
283-
for referencingFilePath := range keys.Keys() {
284-
if h.handleDtsMayChangeOfFileAndExportsOfFile(dtsMayChange, referencingFilePath, invalidateJsFiles) {
285-
return true
286-
}
268+
for referencingFilePath := range h.program.snapshot.referencedMap.getReferencedBy(filePath) {
269+
if h.handleDtsMayChangeOfFileAndExportsOfFile(dtsMayChange, referencingFilePath, invalidateJsFiles) {
270+
return true
287271
}
288272
}
289273
return false

internal/incremental/buildinfotosnapshot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func (t *toSnapshot) setFileInfoAndEmitSignatures() {
122122

123123
func (t *toSnapshot) setReferencedMap() {
124124
for _, entry := range t.buildInfo.ReferencedMap {
125-
t.snapshot.referencedMap.Store(t.toFilePath(entry.FileId), t.toFilePathSet(entry.FileIdListId))
125+
t.snapshot.referencedMap.storeReferences(t.toFilePath(entry.FileId), t.toFilePathSet(entry.FileIdListId))
126126
}
127127
}
128128

internal/incremental/programtosnapshot.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,14 @@ func (t *toProgramSnapshot) computeProgramFileChanges() {
9393
var signature string
9494
newReferences := getReferencedFiles(t.program, file)
9595
if newReferences != nil {
96-
t.snapshot.referencedMap.Store(file.Path(), newReferences)
96+
t.snapshot.referencedMap.storeReferences(file.Path(), newReferences)
9797
}
9898
if t.oldProgram != nil {
9999
if oldFileInfo, ok := t.oldProgram.snapshot.fileInfos.Load(file.Path()); ok {
100100
signature = oldFileInfo.signature
101101
if oldFileInfo.version != version || oldFileInfo.affectsGlobalScope != affectsGlobalScope || oldFileInfo.impliedNodeFormat != impliedNodeFormat {
102102
t.snapshot.addFileToChangeSet(file.Path())
103-
} else if oldReferences, _ := t.oldProgram.snapshot.referencedMap.GetValues(file.Path()); !newReferences.Equals(oldReferences) {
103+
} else if oldReferences, _ := t.oldProgram.snapshot.referencedMap.getReferences(file.Path()); !newReferences.Equals(oldReferences) {
104104
// Referenced files changed
105105
t.snapshot.addFileToChangeSet(file.Path())
106106
} else if newReferences != nil {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package incremental
2+
3+
import (
4+
"iter"
5+
"maps"
6+
"slices"
7+
"sync"
8+
9+
"github.com/microsoft/typescript-go/internal/collections"
10+
"github.com/microsoft/typescript-go/internal/tspath"
11+
)
12+
13+
type referenceMap struct {
14+
references collections.SyncMap[tspath.Path, *collections.Set[tspath.Path]]
15+
referencedBy map[tspath.Path]*collections.Set[tspath.Path]
16+
referenceBy sync.Once
17+
}
18+
19+
func (r *referenceMap) storeReferences(path tspath.Path, refs *collections.Set[tspath.Path]) {
20+
r.references.Store(path, refs)
21+
}
22+
23+
func (r *referenceMap) getReferences(path tspath.Path) (*collections.Set[tspath.Path], bool) {
24+
refs, ok := r.references.Load(path)
25+
return refs, ok
26+
}
27+
28+
func (r *referenceMap) getPathsWithReferences() []tspath.Path {
29+
return slices.Collect(r.references.Keys())
30+
}
31+
32+
func (r *referenceMap) getReferencedBy(path tspath.Path) iter.Seq[tspath.Path] {
33+
r.referenceBy.Do(func() {
34+
r.referencedBy = make(map[tspath.Path]*collections.Set[tspath.Path])
35+
r.references.Range(func(key tspath.Path, value *collections.Set[tspath.Path]) bool {
36+
for ref := range value.Keys() {
37+
set, ok := r.referencedBy[ref]
38+
if !ok {
39+
set = &collections.Set[tspath.Path]{}
40+
r.referencedBy[ref] = set
41+
}
42+
set.Add(key)
43+
}
44+
return true
45+
})
46+
})
47+
refs, ok := r.referencedBy[path]
48+
if ok {
49+
return maps.Keys(refs.Keys())
50+
}
51+
return func(yield func(tspath.Path) bool) {}
52+
}

internal/incremental/snapshot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ type snapshot struct {
188188
fileInfos collections.SyncMap[tspath.Path, *fileInfo]
189189
options *core.CompilerOptions
190190
// Contains the map of ReferencedSet=Referenced files of the file if module emit is enabled
191-
referencedMap collections.SyncManyToManySet[tspath.Path, tspath.Path]
191+
referencedMap referenceMap
192192
// Cache of semantic diagnostics for files with their Path being the key
193193
semanticDiagnosticsPerFile collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName]
194194
// Cache of dts emit diagnostics for files with their Path being the key

internal/incremental/snapshottobuildinfo.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,10 @@ func (t *toBuildInfo) setCompilerOptions() {
231231
}
232232

233233
func (t *toBuildInfo) setReferencedMap() {
234-
keys := slices.Collect(t.snapshot.referencedMap.Keys().Keys())
234+
keys := t.snapshot.referencedMap.getPathsWithReferences()
235235
slices.Sort(keys)
236236
t.buildInfo.ReferencedMap = core.Map(keys, func(filePath tspath.Path) *BuildInfoReferenceMapEntry {
237-
references, _ := t.snapshot.referencedMap.GetValues(filePath)
237+
references, _ := t.snapshot.referencedMap.getReferences(filePath)
238238
return &BuildInfoReferenceMapEntry{
239239
FileId: t.toFileId(filePath),
240240
FileIdListId: t.toFileIdListId(references),

0 commit comments

Comments
 (0)