Skip to content

Commit b1ebfdb

Browse files
committed
MVP finished
1 parent caee542 commit b1ebfdb

File tree

3 files changed

+76
-27
lines changed

3 files changed

+76
-27
lines changed

tests/FSharp.Compiler.Service.Tests2/DepResolving.fs

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ type Node =
1616
AST : ParsedInput
1717
Top : LongIdent
1818
ModuleRefs : LongIdent[]
19+
// Order of the file in the project. Files with lower number cannot depend on files with higher number
20+
Idx : int
1921
}
2022

2123
/// Filenames with dependencies
22-
type Graph = (Node * Node[])[]
24+
type Graph = (string * string[])[]
2325

2426
let extractModuleSegments (stuff : Stuff) : LongIdent[] =
2527
stuff
@@ -40,7 +42,7 @@ type TrieNode =
4042
{
4143
// parent?
4244
// TODO Use ValueTuples if not already
43-
Children : System.Collections.Generic.IDictionary<ModuleSegment, TrieNode>
45+
Children : IDictionary<ModuleSegment, TrieNode>
4446
mutable Reachable : bool
4547
mutable Visited : bool
4648
/// Files/graph nodes represented by this TrieNode
@@ -61,7 +63,7 @@ let rec cloneTrie (trie : TrieNode) : TrieNode =
6163
)
6264
|> dict
6365
// TODO Avoid tow dicts
64-
System.Collections.Generic.Dictionary<_,_>(children)
66+
Dictionary<_,_>(children)
6567
{
6668
GraphNodes = List<_>(trie.GraphNodes)
6769
Children = children
@@ -109,22 +111,22 @@ let buildTrie (nodes : Node[]) : TrieNode =
109111

110112
root
111113

112-
let rec search (trie : TrieNode) (path : LongIdent) : TrieNode option =
114+
let rec searchInTrie (trie : TrieNode) (path : LongIdent) : TrieNode option =
113115
let mutable node = trie
114116
match path with
115117
| [] -> Some trie
116118
| segment :: rest ->
117119
match trie.Children.TryGetValue(segment.idText) with
118120
| true, child ->
119-
search child rest
121+
searchInTrie child rest
120122
| false, _ ->
121123
None
122124

123-
let algorithm (nodes : FileAST list) : Graph =
125+
let detectFileDependencies (nodes : FileAST list) : Graph =
124126
// Create ASTs, extract module refs
125127
let nodes =
126128
nodes
127-
|> List.map (fun (name, ast) ->
129+
|> List.mapi (fun i (name, ast) ->
128130
let typeAndModuleRefs = visit ast
129131
let top = topModuleOrNamespace ast
130132
let moduleRefs = extractModuleSegments typeAndModuleRefs
@@ -133,6 +135,7 @@ let algorithm (nodes : FileAST list) : Graph =
133135
AST = ast
134136
Top = top
135137
ModuleRefs = moduleRefs
138+
Idx = i
136139
}
137140
)
138141
|> List.toArray
@@ -149,7 +152,6 @@ let algorithm (nodes : FileAST list) : Graph =
149152

150153
let markVisited (node : TrieNode) =
151154
if not node.Visited then
152-
printfn $"New node visited"
153155
node.Visited <- true
154156
visited.Add(node)
155157

@@ -158,13 +160,12 @@ let algorithm (nodes : FileAST list) : Graph =
158160

159161
let markReachable (node : TrieNode) =
160162
if not node.Reachable then
161-
printfn $"New node reachable"
162163
node.Reachable <- true
163164
reachable.Add(node)
165+
markVisited node
164166

165167
// Mark root (no prefix) as reachable and visited
166168
markReachable trie
167-
markVisited trie
168169

169170
let rec extend (id : LongIdent) (node : TrieNode) =
170171
let rec extend (node : TrieNode) (id : LongIdent) =
@@ -193,7 +194,8 @@ let algorithm (nodes : FileAST list) : Graph =
193194
// extend a reachable node by 'id', but without creating new nodes, mark all seen nodes as visited and the final one as reachable
194195
|> Seq.choose (extend id)
195196
|> Seq.toArray
196-
reachable.AddRange(newReachables)
197+
newReachables
198+
|> Array.iter markReachable
197199

198200
// Add top-level module/namespace as the first reference (possibly not necessary as maybe already in the list)
199201
let moduleRefs =
@@ -210,32 +212,79 @@ let algorithm (nodes : FileAST list) : Graph =
210212
|> Seq.toArray
211213

212214
// Return the node and its dependencies
213-
node, reachableItems
215+
let deps =
216+
reachableItems
217+
// We know a file can't depend on a file further down in the project definition (or on itself)
218+
|> Seq.filter (fun n -> n.Idx < node.Idx)
219+
|> Seq.map (fun n -> n.Name)
220+
|> Seq.toArray
221+
node.Name, deps
214222
)
215223

216224
[<Test>]
217-
let Foo() =
218-
225+
let TestDepsResolver() =
226+
219227
let A =
220228
"""
221229
module A
222-
open B
223-
let x = B.x
224-
"""
230+
let a = 3
231+
type X = int
232+
"""
225233
let B =
226234
"""
227-
module B
228-
let x = 3
235+
namespace B
236+
let b = 3
237+
"""
238+
let C =
239+
"""
240+
module C.X
241+
let c = 3
242+
"""
243+
let D =
244+
"""
245+
module D
246+
let d : A.X = 3
247+
"""
248+
let E =
249+
"""
250+
module E
251+
let e = C.X.x
252+
open A
253+
let x = a
254+
"""
255+
let F =
256+
"""
257+
module F
258+
open C
259+
let x = X.c
260+
"""
261+
let G =
262+
"""
263+
namespace GH
264+
type A = int
265+
"""
266+
let H =
267+
"""
268+
namespace GH
269+
type B = int
229270
"""
230271

231272
let files = [
232-
"A", A
233-
"B", B
273+
"A.fs", A
274+
"B.fs", B
275+
"C.fs", C
276+
"D.fs", D
277+
"E.fs", E
278+
"F.fs", F
279+
"G.fs", G
280+
"H.fs", H
234281
]
235282
let nodes =
236283
files
237284
|> List.map (fun (name, code) -> name, getParseResults code)
238285

239-
let graph = algorithm nodes
240-
241-
printfn $"%+A{graph}"
286+
let graph = detectFileDependencies nodes
287+
288+
printfn "Detected file dependencies:"
289+
graph
290+
|> Array.iter (fun (file, deps) -> printfn $"{file} -> %+A{deps}")

tests/FSharp.Test.Utilities/TestFramework.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ let initializeSuite () =
448448
let usedEnvVars = c.EnvironmentVariables |> Map.add "FSC" c.FSC
449449
{ c with EnvironmentVariables = usedEnvVars }
450450

451-
logConfig cfg
451+
// logConfig cfg
452452

453453
cfg
454454

tests/service/Common.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ let mkProjectCommandLineArgsSilent (dllName, fileNames) =
104104

105105
let mkProjectCommandLineArgs (dllName, fileNames) =
106106
let args = mkProjectCommandLineArgsSilent (dllName, fileNames)
107-
printfn "dllName = %A, args = %A" dllName args
107+
// TODO uncomment
108+
// printfn "dllName = %A, args = %A" dllName args
108109
args
109-
110110
#if NETCOREAPP
111111
let mkProjectCommandLineArgsForScript (dllName, fileNames) =
112112
[| yield "--simpleresolution"

0 commit comments

Comments
 (0)