@@ -48,7 +48,7 @@ type Node<'Item, 'State, 'Result> =
4848/// <param name =" deps " >Direct dependencies of a node</param >
4949/// <param name =" transitiveDeps " >Transitive dependencies of a node</param >
5050/// <param name =" folder " >A way to fold a single result into existing state</param >
51- let combineResults
51+ let combineResultsOld
5252 ( emptyState : 'State )
5353 ( deps : Node < 'Item , 'State , 'Result >[])
5454 ( transitiveDeps : Node < 'Item , 'State , 'Result >[])
@@ -87,8 +87,58 @@ let combineResults
8787 set.Add biggestDep.Info.Item |> ignore
8888 set
8989 let resultsToAdd =
90- transitiveDeps
90+ transitiveDeps
91+ |> Array.filter ( fun dep -> included.Contains dep.Info.Item = false )
92+ |> Array.distinctBy ( fun dep -> dep.Info.Item)
93+ |> Array.map ( fun dep ->
94+ dep.Result
95+ |> orFail
96+ |> snd
97+ )
98+ let state = Array.fold folder firstState resultsToAdd
99+ state
100+
101+
102+ // TODO Do we need to suppress some error logging if we
103+ // TODO apply the same partial results multiple times?
104+ // TODO Maybe we can enable logging only for the final fold
105+ /// <summary >
106+ /// Combine results of dependencies needed to type-check a 'higher' node in the graph
107+ /// </summary >
108+ /// <param name =" deps " >Direct dependencies of a node</param >
109+ /// <param name =" transitiveDeps " >Transitive dependencies of a node</param >
110+ /// <param name =" folder " >A way to fold a single result into existing state</param >
111+ let combineResults
112+ ( emptyState : 'State )
113+ ( deps : Node < 'Item , 'State , 'Result >[])
114+ ( transitiveDeps : Node < 'Item , 'State , 'Result >[])
115+ ( folder : 'State -> 'Result -> 'State )
116+ : 'State
117+ =
118+ match deps with
119+ | [||] -> emptyState
120+ | _ ->
121+ let orFail value =
122+ value
123+ |> Option.defaultWith ( fun () -> failwith " Unexpected lack of result" )
124+ let firstState = emptyState
125+ // TODO Potential perf optimisation: Keep transDeps in a HashSet from the start,
126+ // avoiding reconstructing the HashSet here
127+
128+ // Add single-file results of remaining transitive deps one-by-one using folder
129+ // Note: Good to preserve order here so that folding happens in file order
130+ let included =
131+ let set = HashSet()
132+ //set.Add biggestDep.Info.Item |> ignore
133+ set
134+ let resultsToAdd =
135+ transitiveDeps
136+ // Sort it by effectively file index.
137+ // For some reason this is needed, otherwise gives 'missing namespace' and other errors when using the resulting state.
138+ // Does this make sense? Should the results be foldable in any order?
139+ |> Array.sortBy ( fun d -> d.Info.Item)
91140 |> Array.filter ( fun dep -> included.Contains dep.Info.Item = false )
141+ |> Array.distinctBy ( fun dep -> dep.Info.Item)
92142 |> Array.map ( fun dep ->
93143 dep.Result
94144 |> orFail
@@ -97,6 +147,7 @@ let combineResults
97147 let state = Array.fold folder firstState resultsToAdd
98148 state
99149
150+
100151// TODO Could be replaced with a simpler recursive approach with memoised per-item results
101152let processGraph < 'Item , 'State , 'Result , 'FinalFileResult when 'Item : equality and 'Item : comparison >
102153 ( graph : Graph < 'Item >)
0 commit comments