@@ -17,33 +17,29 @@ let queryTriePartial (trie: TrieNode) (path: LongIdentifier) : TrieNode option =
17
17
18
18
visit trie path
19
19
20
- let mapNodeToQueryResult ( currentFileIndex : FileIndex ) ( node : TrieNode option ) : QueryTrieNodeResult =
20
+ let mapNodeToQueryResult ( node : TrieNode option ) : QueryTrieNodeResult =
21
21
match node with
22
22
| Some finalNode ->
23
- if
24
- Set.isEmpty finalNode.Files
25
- // If this node exposes files which the current index cannot see, we consider it not to have data at all.
26
- || Set.forall ( fun idx -> idx >= currentFileIndex) finalNode.Files
27
- then
23
+ if Set.isEmpty finalNode.Files then
28
24
QueryTrieNodeResult.NodeDoesNotExposeData
29
25
else
30
26
QueryTrieNodeResult.NodeExposesData( finalNode.Files)
31
27
| None -> QueryTrieNodeResult.NodeDoesNotExist
32
28
33
29
/// <summary>Find a path in the Trie.</summary>
34
- let queryTrie ( currentFileIndex : FileIndex ) ( trie : TrieNode ) ( path : LongIdentifier ) : QueryTrieNodeResult =
35
- queryTriePartial trie path |> mapNodeToQueryResult currentFileIndex
30
+ let queryTrie ( trie : TrieNode ) ( path : LongIdentifier ) : QueryTrieNodeResult =
31
+ queryTriePartial trie path |> mapNodeToQueryResult
36
32
37
33
/// <summary>Same as 'queryTrie' but allows passing in a path combined from two parts, avoiding list allocation.</summary>
38
- let queryTrieDual ( currentFileIndex : FileIndex ) ( trie : TrieNode ) ( path1 : LongIdentifier ) ( path2 : LongIdentifier ) : QueryTrieNodeResult =
34
+ let queryTrieDual ( trie : TrieNode ) ( path1 : LongIdentifier ) ( path2 : LongIdentifier ) : QueryTrieNodeResult =
39
35
match queryTriePartial trie path1 with
40
36
| Some intermediateNode -> queryTriePartial intermediateNode path2
41
37
| None -> None
42
- |> mapNodeToQueryResult currentFileIndex
38
+ |> mapNodeToQueryResult
43
39
44
40
/// Process namespace declaration.
45
41
let processNamespaceDeclaration ( trie : TrieNode ) ( path : LongIdentifier ) ( state : FileContentQueryState ) : FileContentQueryState =
46
- let queryResult = queryTrie state.CurrentFile trie path
42
+ let queryResult = queryTrie trie path
47
43
48
44
match queryResult with
49
45
| QueryTrieNodeResult.NodeDoesNotExist -> state
@@ -53,7 +49,7 @@ let processNamespaceDeclaration (trie: TrieNode) (path: LongIdentifier) (state:
53
49
/// Process an "open" statement.
54
50
/// The statement could link to files and/or should be tracked as an open namespace.
55
51
let processOpenPath ( trie : TrieNode ) ( path : LongIdentifier ) ( state : FileContentQueryState ) : FileContentQueryState =
56
- let queryResult = queryTrie state.CurrentFile trie path
52
+ let queryResult = queryTrie trie path
57
53
58
54
match queryResult with
59
55
| QueryTrieNodeResult.NodeDoesNotExist -> state
@@ -103,13 +99,12 @@ let rec processStateEntry (trie: TrieNode) (state: FileContentQueryState) (entry
103
99
||> Array.fold ( fun state takeParts ->
104
100
let path = List.take takeParts path
105
101
// process the name was if it were a FQN
106
- let stateAfterFullIdentifier =
107
- processIdentifier ( queryTrieDual state.CurrentFile trie [] path) state
102
+ let stateAfterFullIdentifier = processIdentifier ( queryTrieDual trie [] path) state
108
103
109
104
// Process the name in combination with the existing open namespaces
110
105
( stateAfterFullIdentifier, state.OpenNamespaces)
111
106
||> Set.fold ( fun acc openNS ->
112
- let queryResult = queryTrieDual state.CurrentFile trie openNS path
107
+ let queryResult = queryTrieDual trie openNS path
113
108
processIdentifier queryResult acc))
114
109
115
110
| FileContentEntry.NestedModule ( nestedContent = nestedContent) ->
@@ -142,7 +137,7 @@ let collectGhostDependencies (fileIndex: FileIndex) (trie: TrieNode) (result: Fi
142
137
// For each opened namespace, if none of already resolved dependencies define it, return the top-most file that defines it.
143
138
Set.toArray result.OpenedNamespaces
144
139
|> Array.choose ( fun path ->
145
- match queryTrie fileIndex trie path with
140
+ match queryTrie trie path with
146
141
| QueryTrieNodeResult.NodeExposesData _
147
142
| QueryTrieNodeResult.NodeDoesNotExist -> None
148
143
| QueryTrieNodeResult.NodeDoesNotExposeData ->
@@ -201,20 +196,25 @@ let mkGraph (filePairs: FilePairMap) (files: FileInProject array) : Graph<FileIn
201
196
else
202
197
let fileContent = fileContents[ file.Idx]
203
198
204
- let knownFiles = [| 0 .. ( file.Idx - 1 ) |] |> set
199
+ // The Trie we want to use is the one that contains only files before our current index.
200
+ // As we skip implementation files (backed by a signature), we cannot just use the current file index to find the right Trie.
201
+ let trieForFile =
202
+ trie
203
+ |> Array.fold ( fun acc ( idx , t ) -> if idx < file.Idx then t else acc) TrieNode.Empty
204
+
205
205
// File depends on all files above it that define accessible symbols at the root level (global namespace).
206
- let filesFromRoot = trie.Files |> Set.filter ( fun rootIdx -> rootIdx < file.Idx)
206
+ let filesFromRoot =
207
+ trieForFile.Files |> Set.filter ( fun rootIdx -> rootIdx < file.Idx)
207
208
// Start by listing root-level dependencies.
208
- let initialDepsResult =
209
- ( FileContentQueryState.Create file.Idx knownFiles filesFromRoot), fileContent
209
+ let initialDepsResult = ( FileContentQueryState.Create filesFromRoot), fileContent
210
210
// Sequentially process all relevant entries of the file and keep updating the state and set of dependencies.
211
211
let depsResult =
212
212
initialDepsResult
213
213
// Seq is faster than List in this case.
214
- ||> Seq.fold ( processStateEntry trie )
214
+ ||> Seq.fold ( processStateEntry trieForFile )
215
215
216
216
// Add missing links for cases where an unused open namespace did not create a link.
217
- let ghostDependencies = collectGhostDependencies file.Idx trie depsResult
217
+ let ghostDependencies = collectGhostDependencies file.Idx trieForFile depsResult
218
218
219
219
// Add a link from implementation files to their signature files.
220
220
let signatureDependency =
@@ -237,4 +237,6 @@ let mkGraph (filePairs: FilePairMap) (files: FileInProject array) : Graph<FileIn
237
237
|> Array.Parallel.map ( fun file -> file.Idx, findDependencies file)
238
238
|> readOnlyDict
239
239
240
+ let trie = trie |> Array.last |> snd
241
+
240
242
graph, trie
0 commit comments