Skip to content

Commit 5bc6881

Browse files
authored
Upd4 (#138)
1 parent 5af82ac commit 5bc6881

File tree

5 files changed

+91
-91
lines changed

5 files changed

+91
-91
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.57.0] - 2022-03-20
9+
10+
### Changed
11+
12+
- ProjectController.LoadProject now returns an Async bool to indicate eventual completion
13+
- Fix heisen test https://github.com/ionide/proj-info/issues/136
14+
- Multiple agents being created by ProjectSystem
15+
816
## [0.56.0] - 2022-03-19
917

1018
### Changed

src/Ionide.ProjInfo.ProjectSystem/Project.fs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ type internal ProjectPersistentCache(projectFile: string) =
107107

108108
loop ()
109109

110-
member __.SaveCache(lwt, resp) = agent.Post(Save(lwt, resp))
110+
member _.SaveCache(lwt, resp) = agent.Post(Save(lwt, resp))
111111

112-
member __.LoadCache(lwt) =
112+
member _.LoadCache(lwt) =
113113
agent.PostAndReply(fun ch -> Load(lwt, ch))
114114

115115
type private ProjectMessage =
@@ -204,14 +204,14 @@ type internal Project(projectFile, onChange: string -> unit) =
204204

205205
do propsfsw.EnableRaisingEvents <- true
206206

207-
member __.Response
207+
member _.Response
208208
with get () = agent.PostAndReply GetResponse
209209
and set r = agent.Post(SetResponse r)
210210

211-
member __.FileName = fullPath
211+
member _.FileName = fullPath
212212

213213
interface IDisposable with
214-
member __.Dispose() =
214+
member _.Dispose() =
215215
propsfsw.Dispose()
216216
afsw.Dispose()
217217
fsw.Dispose()

src/Ionide.ProjInfo.ProjectSystem/ProjectSystem.fs

Lines changed: 49 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ type ProjectController(toolsPath: ToolsPath, workspaceLoaderFactory: ToolsPath -
4343
let workspaceReady = Event<unit>()
4444
let notify = Event<ProjectResponse>()
4545

46-
4746
let deduplicateBy keySelector (obs: IObservable<'a>) =
4847
obs
4948
|> Observable.synchronize // deals with concurrency issues
@@ -61,37 +60,35 @@ type ProjectController(toolsPath: ToolsPath, workspaceLoaderFactory: ToolsPath -
6160
projs |> List.iter (fun (fileName, _) -> fileName |> ProjectResponse.ProjectChanged |> notify.Trigger)
6261

6362
for (key, group) in projectGroups do
64-
x.LoadWorkspace(group, key)
63+
x.LoadWorkspace(group, key) |> ignore
6564

6665
projectsChanged |> deduplicateBy fst |> Observable.subscribe loadProjects
6766

6867

6968
let updateState (response: ProjectCrackerCache) =
7069
let normalizeOptions (opts: FSharpProjectOptions) =
7170
{ opts with
72-
SourceFiles =
71+
SourceFiles =
7372
opts.SourceFiles
7473
|> Array.filter (FscArguments.isCompileFile)
7574
|> Array.map (Path.GetFullPath)
7675
|> Array.map (fun p -> (p.Chars 0).ToString().ToLower() + p.Substring(1))
77-
OtherOptions =
78-
opts.OtherOptions
79-
|> Array.map
80-
(fun n ->
81-
if FscArguments.isCompileFile (n) then
82-
Path.GetFullPath n
83-
else
84-
n) }
76+
OtherOptions =
77+
opts.OtherOptions
78+
|> Array.map (fun n ->
79+
if FscArguments.isCompileFile (n) then
80+
Path.GetFullPath n
81+
else
82+
n) }
8583

8684
for file in
8785
response.Items
88-
|> List.choose
89-
(function
86+
|> List.choose (function
9087
| ProjectViewerItem.Compile (p, _) -> Some p) do
9188
fileCheckOptions.[file] <- normalizeOptions response.Options
9289

9390

94-
member private x.loadProjects (files: string list) (binaryLogs: BinaryLogGeneration) =
91+
let loadProjects (files: string list) (binaryLogs: BinaryLogGeneration) =
9592
async {
9693
let onChange fn = projectsChanged.OnNext(fn, binaryLogs)
9794

@@ -117,8 +114,7 @@ type ProjectController(toolsPath: ToolsPath, workspaceLoaderFactory: ToolsPath -
117114

118115
let responseFiles =
119116
response.Items
120-
|> List.choose
121-
(function
117+
|> List.choose (function
122118
| ProjectViewerItem.Compile (p, _) -> Some p)
123119

124120
let projInfo: ProjectResult =
@@ -134,8 +130,7 @@ type ProjectController(toolsPath: ToolsPath, workspaceLoaderFactory: ToolsPath -
134130
| ProjectSystemState.LoadedOther (extraInfo, projectFiles, fromDpiCache) ->
135131
let responseFiles =
136132
projectFiles
137-
|> List.choose
138-
(function
133+
|> List.choose (function
139134
| ProjectViewerItem.Compile (p, _) -> Some p)
140135

141136
let projInfo: ProjectResult =
@@ -177,75 +172,77 @@ type ProjectController(toolsPath: ToolsPath, workspaceLoaderFactory: ToolsPath -
177172
return true
178173
}
179174

180-
member private x.LoaderLoop =
181-
MailboxProcessor.Start
182-
(fun agent -> //If couldn't recive new event in 50 ms then just load previous one
183-
let rec loop (previousStatus: (string list * BinaryLogGeneration) option) =
184-
async {
185-
match previousStatus with
186-
187-
| Some (fn, gb) ->
188-
match! agent.TryReceive(50) with
189-
| None -> //If couldn't recive new event in 50 ms then just load previous one
190-
let! _ = x.loadProjects fn gb
191-
return! loop None
192-
| Some (fn2, gb2) when fn2 = fn -> //If recived same load request then wait again (in practice shouldn't happen more than 2 times)
193-
return! loop previousStatus
194-
| Some (fn2, gb2) -> //If recived some other project load previous one, and then wait with the new one
195-
let! _ = x.loadProjects fn gb
196-
return! loop (Some(fn2, gb2))
197-
| None ->
198-
let! (fn, gb) = agent.Receive()
199-
return! loop (Some(fn, gb))
200-
}
201-
202-
loop None)
175+
let loaderLoop =
176+
MailboxProcessor.Start (fun agent -> //If couldn't recive new event in 50 ms then just load previous one
177+
let rec loop (previousStatus: (AsyncReplyChannel<bool> * string list * BinaryLogGeneration) option) =
178+
async {
179+
match previousStatus with
180+
181+
| Some (chan, fn, gb) ->
182+
match! agent.TryReceive(50) with
183+
| None -> //If couldn't recive new event in 50 ms then just load previous one
184+
let! res = loadProjects fn gb
185+
chan.Reply res
186+
return! loop None
187+
| Some (chan2, fn2, gb2) when fn2 = fn -> //If recived same load request then wait again (in practice shouldn't happen more than 2 times)
188+
return! loop previousStatus
189+
| Some (chan2, fn2, gb2) -> //If recived some other project load previous one, and then wait with the new one
190+
let! res = loadProjects fn gb
191+
chan.Reply res
192+
return! loop (Some(chan2, fn2, gb2))
193+
| None ->
194+
let! (chan, fn, gb) = agent.Receive()
195+
return! loop (Some(chan, fn, gb))
196+
}
197+
198+
loop None)
203199

204200
///Event notifies that whole workspace has been loaded
205-
member __.WorkspaceReady = workspaceReady.Publish
201+
member _.WorkspaceReady = workspaceReady.Publish
206202

207203
///Event notifies about any loading events
208-
member __.Notifications = notify.Publish
204+
member _.Notifications = notify.Publish
209205

210-
member __.IsWorkspaceReady = isWorkspaceReady
206+
member _.IsWorkspaceReady = isWorkspaceReady
211207

212208
///Try to get instance of `FSharpProjectOptions` for given `.fs` file
213-
member __.GetProjectOptions(file: string) : FSharpProjectOptions option =
209+
member _.GetProjectOptions(file: string) : FSharpProjectOptions option =
214210
let file = Utils.normalizePath file
215211
fileCheckOptions.TryFind file
216212

217-
member __.SetProjectOptions(file: string, opts: FSharpProjectOptions) =
213+
member _.SetProjectOptions(file: string, opts: FSharpProjectOptions) =
218214
let file = Utils.normalizePath file
219215
fileCheckOptions.AddOrUpdate(file, (fun _ -> opts), (fun _ _ -> opts)) |> ignore
220216

221-
member __.RemoveProjectOptions(file) =
217+
member _.RemoveProjectOptions(file) =
222218
let file = Utils.normalizePath file
223219
fileCheckOptions.TryRemove file |> ignore
224220

225221
///Try to get instance of `FSharpProjectOptions` for given `.fsproj` file
226-
member __.GetProjectOptionsForFsproj(fsprojPath: string) : FSharpProjectOptions option =
222+
member _.GetProjectOptionsForFsproj(fsprojPath: string) : FSharpProjectOptions option =
227223
fileCheckOptions.Values |> Seq.tryFind (fun n -> n.ProjectFileName = fsprojPath)
228224

229225
///Returns a sequance of all known path-to-`.fs` * `FSharpProjectOptions` pairs
230-
member __.ProjectOptions = fileCheckOptions |> Seq.map (|KeyValue|)
226+
member _.ProjectOptions = fileCheckOptions |> Seq.map (|KeyValue|)
231227

232228
///Loads a single project file
233229
member x.LoadProject(projectFileName: string, binaryLogs: BinaryLogGeneration) =
234-
x.LoaderLoop.Post([ projectFileName ], binaryLogs)
230+
loaderLoop.PostAndAsyncReply((fun chan -> chan, [ projectFileName ], binaryLogs))
235231

236232
///Loads a single project file
237233
member x.LoadProject(projectFileName: string) =
238234
x.LoadProject(projectFileName, BinaryLogGeneration.Off)
239235

240236
///Loads a set of project files
241-
member x.LoadWorkspace(files: string list, binaryLogs: BinaryLogGeneration) = x.LoaderLoop.Post(files, binaryLogs)
237+
member x.LoadWorkspace(files: string list, binaryLogs: BinaryLogGeneration) =
238+
loaderLoop.PostAndAsyncReply((fun chan -> chan, files, binaryLogs))
242239

243240
///Loads a set of project files
244241
member x.LoadWorkspace(files: string list) =
245242
x.LoadWorkspace(files, BinaryLogGeneration.Off)
246243

247244
///Finds a list of potential workspaces (solution files/lists of projects) in given dir
248-
member __.PeekWorkspace(dir: string, deep: int, excludedDirs: string list) =
245+
member _.PeekWorkspace(dir: string, deep: int, excludedDirs: string list) =
249246
WorkspacePeek.peek dir deep excludedDirs
250247

251248
interface IDisposable with

test/Ionide.ProjInfo.Tests/FileUtils.fs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,19 @@ let touch (logger: Logger) path =
101101
type FileUtils(logger: Logger) =
102102
let mutable currentDirectory = Environment.CurrentDirectory
103103

104-
member __.cd dir =
104+
member _.cd dir =
105105
logger.debug (eventX "cd '{directory}'" >> setField "directory" dir)
106106
currentDirectory <- dir
107107

108-
member __.rm_rf = rm_rf logger
109-
member __.mkdir_p = mkdir_p logger
110-
member __.cp = cp logger
111-
member __.cp_r = cp_r logger
112-
member __.shellExecRun = shellExecRun logger currentDirectory
113-
member __.shellExecRunNET = shellExecRunNET logger currentDirectory
114-
member __.createFile = createFile logger
115-
member __.unzip = unzip logger
116-
member __.readFile = readFile logger
117-
member __.touch = touch logger
108+
member _.rm_rf = rm_rf logger
109+
member _.mkdir_p = mkdir_p logger
110+
member _.cp = cp logger
111+
member _.cp_r = cp_r logger
112+
member _.shellExecRun = shellExecRun logger currentDirectory
113+
member _.shellExecRunNET = shellExecRunNET logger currentDirectory
114+
member _.createFile = createFile logger
115+
member _.unzip = unzip logger
116+
member _.readFile = readFile logger
117+
member _.touch = touch logger
118118

119119
let writeLines (lines: string list) (stream: StreamWriter) = lines |> List.iter stream.WriteLine

test/Ionide.ProjInfo.Tests/Tests.fs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,8 @@ let createFCS () =
7373
checker
7474

7575
let sleepABit () =
76-
// we wait a bit longer on macos in CI due to apparent slowness
77-
if System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX) then
78-
System.Threading.Thread.Sleep 5000
79-
else
80-
System.Threading.Thread.Sleep 3000
76+
// CI has apparent occasional slowness
77+
System.Threading.Thread.Sleep 5000
8178

8279
[<AutoOpen>]
8380
module ExpectNotification =
@@ -131,7 +128,7 @@ module ExpectNotification =
131128
notifications.Add(arg)
132129
log arg)
133130

134-
member __.Notifications = notifications |> List.ofSeq
131+
member _.Notifications = notifications |> List.ofSeq
135132

136133
let logNotification (logger: Logger) arg =
137134
logger.debug (eventX "notified: {notification}'" >> setField "notification" arg)
@@ -634,8 +631,7 @@ let testProjectNotFound toolsPath workspaceLoader (workspaceFactory: ToolsPath -
634631

635632
Expect.equal parsed.Length 0 "no project loaded"
636633

637-
Expect.equal (watcher.Notifications |> List.item 1) (WorkspaceProjectState.Failed(wrongPath, (GetProjectOptionsErrors.ProjectNotFound(wrongPath)))) "check error type"
638-
)
634+
Expect.equal (watcher.Notifications |> List.item 1) (WorkspaceProjectState.Failed(wrongPath, (GetProjectOptionsErrors.ProjectNotFound(wrongPath)))) "check error type")
639635

640636
let internalGetProjectOptions =
641637
fun (r: FSharpReferencedProject) ->
@@ -683,7 +679,8 @@ let testFCSmap toolsPath workspaceLoader (workspaceFactory: ToolsPath -> IWorksp
683679
let parsed = loader.LoadProjects [ projPath ] |> Seq.toList
684680
let mutable pos = Map.empty
685681

686-
loader.Notifications.Add (function | WorkspaceProjectState.Loaded (po, knownProjects, _) -> pos <- Map.add po.ProjectFileName po pos)
682+
loader.Notifications.Add (function
683+
| WorkspaceProjectState.Loaded (po, knownProjects, _) -> pos <- Map.add po.ProjectFileName po pos)
687684

688685
let fcsPo = FCS.mapToFSharpProjectOptions parsed.Head parsed
689686

@@ -707,7 +704,7 @@ let testFCSmap toolsPath workspaceLoader (workspaceFactory: ToolsPath -> IWorksp
707704

708705
Expect.isNonEmpty uses "all symbols usages"
709706

710-
)
707+
)
711708

712709
let testFCSmapManyProj toolsPath workspaceLoader (workspaceFactory: ToolsPath -> IWorkspaceLoader) =
713710
testCase
@@ -733,7 +730,7 @@ let testFCSmapManyProj toolsPath workspaceLoader (workspaceFactory: ToolsPath ->
733730
Expect.equal tar dpoPo.TargetPath (sprintf "p2p key is TargetPath, fsc projet options was '%A'" fcsPO)
734731

735732
let testDir = inDir fs "load_sample_fsc"
736-
copyDirFromAssets fs ``sample3 Netsdk projs``.ProjDir testDir
733+
copyDirFromAssets fs ``sample3 Netsdk projs``.ProjDir testDir
737734

738735
let projPath = testDir / (``sample3 Netsdk projs``.ProjectFile)
739736

@@ -744,7 +741,8 @@ let testFCSmapManyProj toolsPath workspaceLoader (workspaceFactory: ToolsPath ->
744741
let parsed = loader.LoadProjects [ projPath ] |> Seq.toList
745742
let mutable pos = Map.empty
746743

747-
loader.Notifications.Add (function | WorkspaceProjectState.Loaded (po, knownProjects, _) -> pos <- Map.add po.ProjectFileName po pos)
744+
loader.Notifications.Add (function
745+
| WorkspaceProjectState.Loaded (po, knownProjects, _) -> pos <- Map.add po.ProjectFileName po pos)
748746

749747
let fcsPo = FCS.mapToFSharpProjectOptions parsed.Head parsed
750748
let hasCSharpRef = fcsPo.OtherOptions |> Seq.exists (fun opt -> opt.StartsWith "-r:" && opt.EndsWith "l1.dll")
@@ -756,7 +754,7 @@ let testFCSmapManyProj toolsPath workspaceLoader (workspaceFactory: ToolsPath ->
756754
Expect.equal hasFSharpRef true "Should have direct dll reference to F# reference"
757755
Expect.equal hasFSharpProjectRef true "Should have project reference to F# reference"
758756

759-
)
757+
)
760758

761759
let testSample2WithBinLog toolsPath workspaceLoader (workspaceFactory: ToolsPath -> IWorkspaceLoader) =
762760
testCase
@@ -870,7 +868,7 @@ module ExpectProjectSystemNotification =
870868
notifications.Add(arg)
871869
log arg)
872870

873-
member __.Notifications = notifications |> List.ofSeq
871+
member _.Notifications = notifications |> List.ofSeq
874872

875873
let logNotification (logger: Logger) arg =
876874
logger.debug (eventX "notified: {notification}'" >> setField "notification" arg)
@@ -890,9 +888,8 @@ let testLoadProject toolsPath =
890888

891889
let projResult = ProjectLoader.getProjectInfo projPath [] BinaryLogGeneration.Off []
892890

893-
match projResult with
894-
| Result.Ok proj ->
895-
Expect.equal proj.ProjectFileName projPath "project file names"
891+
match projResult with
892+
| Result.Ok proj -> Expect.equal proj.ProjectFileName projPath "project file names"
896893
| Result.Error err -> failwith $"{err}"
897894

898895
)
@@ -910,9 +907,9 @@ let testProjectSystem toolsPath workspaceLoader workspaceFactory =
910907

911908
use controller = new ProjectSystem.ProjectController(toolsPath, workspaceFactory)
912909
let watcher = watchNotifications logger controller
913-
controller.LoadProject(projPath)
910+
let result = controller.LoadProject(projPath) |> Async.RunSynchronously
914911

915-
sleepABit ()
912+
Expect.isTrue result "load succeeds"
916913

917914
let parsed = controller.ProjectOptions |> Seq.toList |> List.map (snd)
918915
let fcsPo = parsed.Head
@@ -950,10 +947,8 @@ let testProjectSystemOnChange toolsPath workspaceLoader workspaceFactory =
950947

951948
use controller = new ProjectSystem.ProjectController(toolsPath, workspaceFactory)
952949
let watcher = watchNotifications logger controller
953-
controller.LoadProject(projPath)
954-
955-
sleepABit ()
956-
950+
let result = controller.LoadProject(projPath) |> Async.RunSynchronously
951+
Expect.isTrue result "load succeeds"
957952

958953
[ workspace false
959954
loading "n1.fsproj"

0 commit comments

Comments
 (0)