From de453f7f6292f436e1af769bedef202b6d40930c Mon Sep 17 00:00:00 2001 From: Jimmy Byrd Date: Fri, 16 Feb 2024 16:07:51 -0500 Subject: [PATCH] Slightly better loading error messages (#1234) * Log cancelled as warn, better loading project error message * Refactor selectProject * Log cancellation as info * formatting --- src/FsAutoComplete.Core/AdaptiveExtensions.fs | 27 +- .../AdaptiveExtensions.fsi | 14 + .../LspServers/AdaptiveFSharpLspServer.fs | 445 +++++++----------- .../LspServers/AdaptiveServerState.fs | 176 ++++--- .../LspServers/AdaptiveServerState.fsi | 2 +- 5 files changed, 330 insertions(+), 334 deletions(-) diff --git a/src/FsAutoComplete.Core/AdaptiveExtensions.fs b/src/FsAutoComplete.Core/AdaptiveExtensions.fs index 26820e83d..60d4c503b 100644 --- a/src/FsAutoComplete.Core/AdaptiveExtensions.fs +++ b/src/FsAutoComplete.Core/AdaptiveExtensions.fs @@ -8,7 +8,6 @@ open IcedTasks open System.Threading - [] module AdaptiveExtensions = @@ -286,6 +285,13 @@ module AMap = HashMap.union removeOps changes |> HashMapDelta + let tryFindR (reason: 'a) (key: 'Key) (map: amap<'Key, 'Value>) : aval> = + aval { + match! AMap.tryFind key map with + | Some x -> return Ok x + | None -> return Error reason + } + /// Adaptively looks up the given key in the map and flattens the value to be easily worked with. Note that this operation should not be used extensively since its resulting aval will be re-evaluated upon every change of the map. let tryFindAndFlatten (key: 'Key) (map: amap<'Key, aval>>) = aval { @@ -294,6 +300,7 @@ module AMap = | None -> return None } + /// Adaptively looks up the given key in the map and binds the value to be easily worked with. Note that this operation should not be used extensively since its resulting aval will be re-evaluated upon every change of the map. let tryFindA (key: 'Key) (map: amap<'Key, #aval<'Value>>) = aval { @@ -741,6 +748,15 @@ module AsyncAVal = let mapOption (f: 'a -> CancellationToken -> 'b) (value: asyncaval<'a option>) : asyncaval<'b option> = mapSync (fun data ctok -> data |> Option.map (fun d -> f d ctok)) value + + /// Returns a new async adaptive value that adaptively applies the mapping function to the given + /// optional adaptive inputs. + let mapResult + (f: 'a -> CancellationToken -> 'b) + (value: asyncaval>) + : asyncaval> = + mapSync (fun data ctok -> data |> Result.map (fun d -> f d ctok)) value + type AsyncAValBuilder() = member inline x.MergeSources(v1: asyncaval<'T1>, v2: asyncaval<'T2>) = (v1, v2) @@ -829,3 +845,12 @@ module AMapAsync = | Some x -> return! x | None -> return None } + + + /// Adaptively looks up the given key in the map and flattens the value to be easily worked with. Note that this operation should not be used extensively since its resulting aval will be re-evaluated upon every change of the map. + let tryFindAndFlattenR reason (key: 'Key) (map: amap<'Key, asyncaval>>) = + asyncAVal { + match! AMap.tryFind key map with + | Some x -> return! x + | None -> return Error reason + } diff --git a/src/FsAutoComplete.Core/AdaptiveExtensions.fsi b/src/FsAutoComplete.Core/AdaptiveExtensions.fsi index 0c725f3c3..5a758f0cc 100644 --- a/src/FsAutoComplete.Core/AdaptiveExtensions.fsi +++ b/src/FsAutoComplete.Core/AdaptiveExtensions.fsi @@ -79,6 +79,7 @@ module ASet = FSharp.Data.Adaptive.amap<'a, 'b> module AMap = + open FSharp.Data.Adaptive /// A simple multi-map implementation. type internal MultiSetMap<'k, 'v> = FSharp.Data.Adaptive.HashMap<'k, FSharp.Data.Adaptive.HashSet<'v>> @@ -109,6 +110,8 @@ module AMap = override InputChangedObject: t: obj * o: FSharp.Data.Adaptive.IAdaptiveObject -> unit + val tryFindR: reason: 'a -> key: 'Key -> map: amap<'Key, 'Value> -> aval> + /// Adaptively looks up the given key in the map and flattens the value to be easily worked with. Note that this operation should not be used extensively since its resulting aval will be re-evaluated upon every change of the map. val tryFindAndFlatten: key: 'Key -> @@ -199,6 +202,7 @@ module Extensions = (System.Threading.CancellationToken -> System.Runtime.CompilerServices.TaskAwaiter<'a>) module AsyncAVal = + open System.Threading /// /// Evaluates the given adaptive value and returns a Task containing the value. @@ -314,6 +318,9 @@ module AsyncAVal = val mapOption: f: ('a -> System.Threading.CancellationToken -> 'b) -> value: asyncaval<'a option> -> asyncaval<'b option> + val mapResult: + f: ('a -> CancellationToken -> 'b) -> value: asyncaval> -> asyncaval> + type AsyncAValBuilder = new: unit -> AsyncAValBuilder @@ -355,6 +362,7 @@ module AsyncAValBuilderExtensions = member inline BindReturn: value: asyncaval<'T1> * mapping: ('T1 -> 'T2) -> asyncaval<'T2> module AMapAsync = + open FSharp.Data.Adaptive /// /// Adaptively maps over the given map lifting the value in the map to be an asyncaval. @@ -380,3 +388,9 @@ module AMapAsync = /// Adaptively looks up the given key in the map and flattens the value to be easily worked with. Note that this operation should not be used extensively since its resulting aval will be re-evaluated upon every change of the map. val tryFindAndFlatten: key: 'Key -> map: FSharp.Data.Adaptive.amap<'Key, asyncaval<'Value option>> -> asyncaval<'Value option> + + val tryFindAndFlattenR: + reason: 'Error -> + key: 'Key -> + map: amap<'Key, asyncaval>> -> + asyncaval> diff --git a/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs b/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs index 130161c96..36ad6070e 100644 --- a/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs +++ b/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs @@ -40,6 +40,7 @@ open IcedTasks open System.Threading.Tasks open FsAutoComplete.FCSPatches open Helpers +open System.Runtime.ExceptionServices type AdaptiveFSharpLspServer (workspaceLoader: IWorkspaceLoader, lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFactory) = @@ -48,6 +49,7 @@ type AdaptiveFSharpLspServer let logger = LogProvider.getLoggerFor () + let fantomasLogger = LogProvider.getLoggerByName "Fantomas" let fantomasService: FantomasService = new LSPFantomasService() :> FantomasService @@ -62,8 +64,8 @@ type AdaptiveFSharpLspServer [] let rec (|Cancelled|_|) (e: exn) = match e with - | :? TaskCanceledException -> ValueSome() - | :? OperationCanceledException -> ValueSome() + | :? TaskCanceledException -> ValueSome(e) + | :? OperationCanceledException -> ValueSome(e) | :? System.AggregateException as aex -> if aex.InnerExceptions.Count = 1 then (|Cancelled|_|) aex.InnerException @@ -71,9 +73,16 @@ type AdaptiveFSharpLspServer ValueNone | _ -> ValueNone - let returnException e = + let logException e cfg = match e with - | Cancelled -> LspResult.requestCancelled + | Cancelled e -> logger.info (cfg >> Log.addExn e) + | e -> logger.error (cfg >> Log.addExn e) + + let returnException e logCfg = + logException e logCfg + + match e with + | Cancelled _ -> LspResult.requestCancelled | e -> LspResult.internalError (string e) @@ -246,8 +255,8 @@ type AdaptiveFSharpLspServer | (FormatDocumentResponse.Error ex) -> return! LspResult.internalError ex with e -> trace |> Tracing.recordException e - logger.error (Log.setMessage "HandleFormatting Request Errored {p}" >> Log.addExn e) - return! returnException e + let logCfg = Log.setMessage "HandleFormatting Request Errored" + return! returnException e logCfg } member __.ScriptFileProjectOptions = state.ScriptFileProjectOptions.Publish @@ -370,13 +379,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "Initialize Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.Initialized(p: InitializedParams) = @@ -392,11 +399,10 @@ type AdaptiveFSharpLspServer trace |> Tracing.recordException e - logger.error ( - Log.setMessage "Initialized Request Errored {p}" - >> Log.addContextDestructured "p" p - >> Log.addExn e - ) + logException + e + (Log.setMessage "Initialized Request Errored {p}" + >> Log.addContextDestructured "p" p) return () } @@ -420,11 +426,10 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( - Log.setMessage "TextDocumentDidOpen Request Errored {p}" - >> Log.addContextDestructured "p" p - >> Log.addExn e - ) + logException + e + (Log.setMessage "TextDocumentDidOpen Request Errored {p}" + >> Log.addContextDestructured "p" p) return () } @@ -447,11 +452,10 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( - Log.setMessage "TextDocumentDidClose Request Errored {p}" - >> Log.addContextDestructured "p" p - >> Log.addExn e - ) + logException + e + (Log.setMessage "TextDocumentDidClose Request Errored {p}" + >> Log.addContextDestructured "p" p) return () } @@ -475,11 +479,10 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( - Log.setMessage "TextDocumentDidChange Request Errored {p}" - >> Log.addContextDestructured "p" p - >> Log.addExn e - ) + logException + e + (Log.setMessage "TextDocumentDidChange Request Errored {p}" + >> Log.addContextDestructured "p" p) return () } @@ -512,11 +515,10 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( - Log.setMessage "TextDocumentDidSave Request Errored {p}" - >> Log.addContextDestructured "p" p - >> Log.addExn e - ) + logException + e + (Log.setMessage "TextDocumentDidSave Request Errored {p}" + >> Log.addContextDestructured "p" p) return () } @@ -686,13 +688,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentCompletion Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.CompletionItemResolve(ci: CompletionItem) = @@ -791,13 +791,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "CompletionItemResolve Request Errored {p}" >> Log.addContextDestructured "p" ci - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentSignatureHelp(p: SignatureHelpParams) = @@ -857,13 +855,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentSignatureHelp Request: {params}" >> Log.addContextDestructured "params" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentHover(p: TextDocumentPositionParams) = @@ -949,13 +945,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentHover Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentPrepareRename p = @@ -1041,13 +1035,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentRename Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentDefinition(p: TextDocumentPositionParams) = @@ -1071,13 +1063,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentDefinition Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentTypeDefinition(p: TextDocumentPositionParams) = @@ -1101,13 +1091,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentTypeDefinition Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentReferences(p: ReferenceParams) = @@ -1137,13 +1125,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentReferences Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentDocumentHighlight(p: TextDocumentPositionParams) = @@ -1178,13 +1164,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentDocumentHighlight Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -1241,13 +1225,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentImplementation Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.TextDocumentDocumentSymbol(p: DocumentSymbolParams) = @@ -1262,26 +1244,23 @@ type AdaptiveFSharpLspServer ) let fn = p.TextDocument.GetFilePath() |> Utils.normalizePath + let! decls = state.GetDeclarations fn |> AsyncResult.ofStringErr - match! state.GetDeclarations fn with - | Some decls -> - return - decls - |> Array.collect (fun top -> - getSymbolInformations p.TextDocument.Uri state.GlyphToSymbolKind top (fun _s -> true)) - |> U2.First - |> Some - | None -> return! LspResult.internalError $"No declarations for {fn}" + return + decls + |> Array.collect (fun top -> + getSymbolInformations p.TextDocument.Uri state.GlyphToSymbolKind top (fun _s -> true)) + |> U2.First + |> Some with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentDocumentSymbol Request Errored {p}" >> Log.addContextDestructured "p" p >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -1315,13 +1294,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "WorkspaceSymbol Request Errored {p}" >> Log.addContextDestructured "p" symbolRequest - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentFormatting(p: DocumentFormattingParams) = @@ -1357,13 +1334,12 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentFormatting Request Errored {p}" >> Log.addContextDestructured "p" p >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentRangeFormatting(p: DocumentRangeFormattingParams) = @@ -1410,13 +1386,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentRangeFormatting Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -1437,10 +1411,15 @@ type AdaptiveFSharpLspServer async { try return! codeFix codeActionParams - with e -> + with + | Cancelled e -> + ExceptionDispatchInfo.Capture(e).Throw() + return failwith "Unreachable" + | e -> logger.error ( Log.setMessage "Exception in CodeFix: {error}" - >> Log.addContextDestructured "error" (e.ToString()) + >> Log.addContextDestructured "error" (e.Message) + >> Log.addExn e ) return Ok [] @@ -1484,13 +1463,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentCodeAction Request Errored {p}" >> Log.addContextDestructured "p" codeActionParams - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.TextDocumentCodeLens(p: CodeLensParams) = @@ -1505,30 +1482,26 @@ type AdaptiveFSharpLspServer ) let fn = p.TextDocument.GetFilePath() |> Utils.normalizePath + let! decls = state.GetDeclarations fn |> AsyncResult.ofStringErr - match! state.GetDeclarations(fn) with - | None -> return None - | Some decls -> - let config = state.Config + let config = state.Config - let res = - [| if config.LineLens.Enabled <> "replaceCodeLens" then - if config.CodeLenses.Signature.Enabled then - yield! decls |> Array.collect (getCodeLensInformation p.TextDocument.Uri "signature") - if config.CodeLenses.References.Enabled then - yield! decls |> Array.collect (getCodeLensInformation p.TextDocument.Uri "reference") |] + let res = + [| if config.LineLens.Enabled <> "replaceCodeLens" then + if config.CodeLenses.Signature.Enabled then + yield! decls |> Array.collect (getCodeLensInformation p.TextDocument.Uri "signature") + if config.CodeLenses.References.Enabled then + yield! decls |> Array.collect (getCodeLensInformation p.TextDocument.Uri "reference") |] - return Some res + return Some res with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentCodeLens Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.CodeLensResolve(p: CodeLens) = @@ -1591,13 +1564,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "CodeLensResolve - Operation failed on {file}" >> Log.addContextDestructured "file" filePath - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } let writePayload (sourceFile: string, triggerPos: pos, usageLocations: range[]) = @@ -1700,11 +1671,10 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( - Log.setMessage "WorkspaceDidChangeWatchedFiles Request Errored {p}" - >> Log.addContextDestructured "p" p - >> Log.addExn e - ) + logException + e + (Log.setMessage "WorkspaceDidChangeWatchedFiles Request Errored {p}" + >> Log.addContextDestructured "p" p) } override __.WorkspaceDidChangeConfiguration(p: DidChangeConfigurationParams) = @@ -1729,11 +1699,10 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( - Log.setMessage "WorkspaceDidChangeConfiguration Request Errored {p}" - >> Log.addContextDestructured "p" p - >> Log.addExn e - ) + logException + e + (Log.setMessage "WorkspaceDidChangeConfiguration Request Errored {p}" + >> Log.addContextDestructured "p" p) } override __.TextDocumentFoldingRange(rangeP: FoldingRangeParams) = @@ -1761,13 +1730,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentFoldingRange Request Errored {p}" >> Log.addContextDestructured "p" rangeP - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.TextDocumentSelectionRange(selectionRangeP: SelectionRangeParams) = @@ -1807,13 +1774,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentSelectionRange Request Errored {p}" >> Log.addContextDestructured "p" selectionRangeP - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentSemanticTokensFull(p: SemanticTokensParams) : AsyncLspResult = @@ -1833,13 +1798,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentSemanticTokensFull Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -1861,13 +1824,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentSemanticTokensRange Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentInlayHint(p: InlayHintParams) : AsyncLspResult = @@ -1966,13 +1927,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentInlayHint Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentInlineValue(p: InlineValueParams) = @@ -2008,13 +1967,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "TextDocumentInlineValue Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } //unsupported -- begin @@ -2128,13 +2085,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "CallHierarchyIncomingCalls Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -2184,13 +2139,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "CallHierarchyPrepareParams Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.TextDocumentPrepareTypeHierarchy p = x.logUnimplementedRequest p @@ -2250,13 +2203,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpSignature Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.FSharpSignatureData(p: TextDocumentPositionParams) = @@ -2287,13 +2238,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpSignatureData Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -2341,13 +2290,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDocumentationGenerator Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FSharpLineLens(p: ProjectParms) = @@ -2363,23 +2310,20 @@ type AdaptiveFSharpLspServer let fn = p.Project.GetFilePath() |> Utils.normalizePath - match! state.GetDeclarations fn with - | None -> return! LspResult.internalError $"No declarations found for {fn}" - | Some decls -> - let decls = decls |> Array.map (fun d -> d, fn) + let! decls = state.GetDeclarations fn |> AsyncResult.ofStringErr - return Some { Content = CommandResponse.declarations FsAutoComplete.JsonSerializer.writeJson decls } + let decls = decls |> Array.map (fun d -> d, fn) + + return Some { Content = CommandResponse.declarations FsAutoComplete.JsonSerializer.writeJson decls } with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpLineLense Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FSharpWorkspaceLoad(p: WorkspaceLoadParms) = @@ -2406,13 +2350,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpWorkspaceLoad Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -2444,13 +2386,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpWorkspacePeek Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FSharpProject(p: ProjectParms) = @@ -2484,13 +2424,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpWorkspacePeek Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -2520,13 +2458,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDotnetNewList Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FSharpDotnetNewRun(p: DotnetNewRunRequest) = @@ -2549,13 +2485,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDotnetNewRun Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FSharpDotnetAddProject(p: DotnetProjectRequest) = @@ -2579,13 +2513,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDotnetAddProject Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FSharpDotnetRemoveProject(p: DotnetProjectRequest) = @@ -2608,13 +2540,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDotnetRemoveProject Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FSharpDotnetSlnAdd(p: DotnetProjectRequest) = @@ -2637,13 +2567,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDotnetSlnAdd Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.FSharpHelp(p: TextDocumentPositionParams) = @@ -2668,13 +2596,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpHelp Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.FSharpDocumentation(p: TextDocumentPositionParams) = @@ -2710,13 +2636,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDocumentation Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.FSharpDocumentationSymbol(p: DocumentationForSymbolRequest) = @@ -2756,13 +2680,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpDocumentationSymbol Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.LoadAnalyzers(path) = @@ -2810,13 +2732,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FSharpPipelineHints Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FsProjMoveFileUp(p: DotnetFileRequest) = @@ -2839,13 +2759,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjMoveFileUp Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -2869,13 +2787,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjMoveFileDown Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -2899,13 +2815,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjAddFileAbove Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FsProjAddFileBelow(p: DotnetFile2Request) = @@ -2928,13 +2842,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjAddFileBelow Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override __.FsProjRenameFile(p: DotnetRenameFileRequest) = @@ -2957,13 +2869,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjRenameFile Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } @@ -2987,13 +2897,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjAddFile Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override _.FsProjRemoveFile(p: DotnetFileRequest) = @@ -3022,13 +2930,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjRemoveFile Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override _.FsProjAddExistingFile(p: DotnetFileRequest) = @@ -3051,13 +2957,11 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( + let logCfg = Log.setMessage "FsProjAddExistingFile Request Errored {p}" >> Log.addContextDestructured "p" p - >> Log.addExn e - ) - return! returnException e + return! returnException e logCfg } override x.Dispose() = disposables.Dispose() @@ -3077,11 +2981,10 @@ type AdaptiveFSharpLspServer with e -> trace |> Tracing.recordException e - logger.error ( - Log.setMessage "WorkDoneProgressCancel Request Errored {p}" - >> Log.addContextDestructured "token" token - >> Log.addExn e - ) + logException + e + (Log.setMessage "WorkDoneProgressCancel Request Errored {p}" + >> Log.addContextDestructured "token" token) return () } diff --git a/src/FsAutoComplete/LspServers/AdaptiveServerState.fs b/src/FsAutoComplete/LspServers/AdaptiveServerState.fs index e61c79232..cf399f7c3 100644 --- a/src/FsAutoComplete/LspServers/AdaptiveServerState.fs +++ b/src/FsAutoComplete/LspServers/AdaptiveServerState.fs @@ -67,6 +67,21 @@ type LoadedProject = member x.ProjectFileName = x.FSharpProjectOptions.ProjectFileName static member op_Implicit(x: LoadedProject) = x.FSharpProjectOptions +/// The reality is a file can be in multiple projects +/// This is extracted to make it easier to do some type of customized select in the future +type IFindProject = + abstract member FindProject: + sourceFile: string * projects: LoadedProject seq -> Result + +type FindFirstProject() = + interface IFindProject with + member x.FindProject(sourceFile, projects) = + projects + |> Seq.sortBy (fun p -> p.ProjectFileName) + |> Seq.tryFind (fun p -> p.SourceFiles |> Array.exists (fun f -> f = UMX.untag sourceFile)) + |> Result.ofOption (fun () -> + $"Couldn't find a corresponding project for {sourceFile}. Have the projects loaded yet or have you tried restoring your project/solution?") + type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFactory, workspaceLoader: IWorkspaceLoader) = @@ -74,10 +89,8 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let thisType = typeof let disposables = new Disposables.CompositeDisposable() - /// The reality is a file can be in multiple projects - /// This is extracted to make it easier to do some type of customized select - /// in the future - let selectProject projs = projs |> List.tryHead + + let projectSelector = cval (FindFirstProject()) let rootPath = cval None @@ -706,7 +719,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac |> ASet.mapAtoAMap (UMX.untag >> AdaptiveFile.GetLastWriteTimeUtc) let cb = - projChanges.AddCallback(fun _old delta -> + projChanges.AddWeakCallback(fun _old delta -> logger.info ( Log.setMessage "Loading projects because of {delta}" >> Log.addContextDestructured "delta" delta @@ -908,6 +921,11 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac | (true, v) -> Some v | _ -> None + let getOpenFileTokenOrDefault filePath = + match tryGetOpenFileToken filePath with + | Some v -> v.Token + | None -> CancellationToken.None + let openFiles = cmap, cval> () let openFilesReadOnly = openFiles |> AMap.map (fun _ x -> x :> aval<_>) @@ -1002,7 +1020,8 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac // ignore if already cancelled () - let resetCancellationToken filePath = + let resetCancellationToken (filePath: string) = + let adder _ = new CancellationTokenSource() let updater _key value = @@ -1130,8 +1149,8 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let! projs = asyncOption { - let! cts = tryGetOpenFileToken filePath - use linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ctok, cts.Token) + let cts = getOpenFileTokenOrDefault filePath + use linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ctok, cts) let! opts = checker.GetProjectOptionsFromScript(filePath, file.Source, tfmConfig) @@ -1144,12 +1163,14 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac LanguageVersion = LanguageVersionShim.fromFSharpProjectOptions opts } } - return file, Option.toList projs + return file, (Option.toList projs |> Ok) else let! projs = sourceFileToProjectOptions - |> AMap.tryFind filePath - |> AVal.map (Option.defaultValue []) + |> AMap.tryFindR + $"Couldn't find {filePath} in LoadedProjects. Have the projects loaded yet or have you tried restoring your project/solution?" + filePath + return file, projs }) @@ -1157,14 +1178,14 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let allFSharpFilesAndProjectOptions = let wins = openFilesToChangesAndProjectOptions - |> AMap.map (fun _k v -> v |> AsyncAVal.mapSync (fun (file, projects) _ -> Some file, projects)) + |> AMap.map (fun _k v -> v |> AsyncAVal.mapSync (fun (file, projects) _ -> file, projects)) let loses = sourceFileToProjectOptions |> AMap.map (fun filePath v -> asyncAVal { let! file = getLatestFileChange filePath - return (Some file, v) + return (file, Ok v) }) AMap.union loses wins @@ -1175,16 +1196,17 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let allFilesParsed = allFSharpFilesAndProjectOptions - |> AMapAsync.mapAsyncAVal (fun _filePath (file, options: LoadedProject list) _ctok -> + |> AMapAsync.mapAsyncAVal (fun _filePath (file, options: Result) _ctok -> asyncAVal { let! (checker: FSharpCompilerServiceChecker) = checker + and! selectProject = projectSelector return! - asyncOption { - let! project = options |> selectProject + asyncResult { + let! options = options + let! project = selectProject.FindProject(file.FileName, options) let options = project.FSharpProjectOptions let parseOpts = Utils.projectOptionsToParseOptions project.FSharpProjectOptions - let! file = file return! parseFile checker file parseOpts options } @@ -1205,10 +1227,16 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let getAllFilesToProjectOptionsSelected () = async { let! set = getAllFilesToProjectOptions () + let selectProject = projectSelector |> AVal.force + let findProject file projects = selectProject.FindProject(file, projects) return set - |> Array.choose (fun (k, v) -> selectProject v |> Option.map (fun v -> k, v)) + |> Array.choose (fun (k, v) -> + v + |> Result.bind (findProject k) + |> Result.toOption + |> Option.map (fun v -> k, v)) } let getAllProjectOptions () = @@ -1221,6 +1249,8 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac |> Array.map (AsyncAVal.forceAsync) |> Async.parallel75 + let set = set |> Array.choose (Result.toOption) + return set |> Array.collect (List.toArray) } @@ -1233,7 +1263,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac asyncAVal { match! allFilesToFSharpProjectOptions |> AMapAsync.tryFindA filePath with | Some projs -> return projs - | None -> return [] + | None -> return Error $"Couldn't find project for {filePath}. Have you tried restoring your project/solution?" } let autoCompleteItems @@ -1306,7 +1336,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac >> Log.addContextDestructured "error" e ) - return failwith e + return Error e | Ok parseAndCheck -> logger.info ( Log.setMessage "Typecheck completed successfully for {file}" @@ -1332,7 +1362,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac ) - return parseAndCheck + return Ok parseAndCheck } /// Bypass Adaptive checking and tell the checker to check a file @@ -1367,11 +1397,17 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac asyncAVal { let file = info.Source.FileName let! checker = checker + and! selectProject = projectSelector return - option { - let! opts = selectProject projectOptions - return! checker.TryGetRecentCheckResultsForFile(file, opts.FSharpProjectOptions, info.Source) + result { + let! projectOptions = projectOptions + let! opts = selectProject.FindProject(file, projectOptions) + + return! + checker.TryGetRecentCheckResultsForFile(file, opts.FSharpProjectOptions, info.Source) + |> Result.ofOption (fun () -> + $"No recent typecheck results for {file}. This may be ok if the file has not been checked yet.") } }) @@ -1379,14 +1415,16 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac openFilesToChangesAndProjectOptions |> AMapAsync.mapAsyncAVal (fun _ (info, projectOptions) ctok -> asyncAVal { - let file = info.Source.FileName + let file = info.FileName let! checker = checker + and! selectProject = projectSelector return! - asyncOption { - let! opts = selectProject projectOptions - let! cts = tryGetOpenFileToken file - use linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ctok, cts.Token) + asyncResult { + let! projectOptions = projectOptions + let! opts = selectProject.FindProject(file, projectOptions) + let cts = getOpenFileTokenOrDefault file + use linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ctok, cts) return! parseAndCheckFile checker info opts.FSharpProjectOptions true @@ -1395,41 +1433,42 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac }) - let getParseResults filePath = allFilesParsed |> AMapAsync.tryFindAndFlatten filePath + let getParseResults filePath = + allFilesParsed + |> AMapAsync.tryFindAndFlattenR $"No parse results found for {filePath}" filePath - let getOpenFileTypeCheckResults filePath = openFilesToCheckedFilesResults |> AMapAsync.tryFindAndFlatten (filePath) + let getOpenFileTypeCheckResults filePath = + openFilesToCheckedFilesResults + |> AMapAsync.tryFindAndFlattenR $"No check results found for {filePath}" (filePath) let getOpenFileRecentTypeCheckResults filePath = - openFilesToRecentCheckedFilesResults |> AMapAsync.tryFindAndFlatten (filePath) + openFilesToRecentCheckedFilesResults + |> AMapAsync.tryFindAndFlattenR + $"No recent typecheck results for {filePath}. This may be ok if the file has not been checked yet." + (filePath) + + let forceGetParseResults filePath = getParseResults filePath |> AsyncAVal.forceAsync - let forceGetParseResults filePath = - async { - let! results = getParseResults filePath |> AsyncAVal.forceAsync - return results |> Result.ofOption (fun () -> $"No parse results for {filePath}") - } let forceGetOpenFileRecentTypeCheckResults filePath = - async { + asyncResult { let! results = getOpenFileRecentTypeCheckResults filePath |> AsyncAVal.forceAsync - return results |> Result.ofOption (fun () -> $"No typecheck results for {filePath}") + return results } let forceGetOpenFileTypeCheckResults (filePath: string) = - async { - let! results = getOpenFileTypeCheckResults (filePath) |> AsyncAVal.forceAsync - return results |> Result.ofOption (fun () -> $"No typecheck results for {filePath}") - } + getOpenFileTypeCheckResults (filePath) |> AsyncAVal.forceAsync + let forceGetProjectOptions filePath = asyncAVal { let! projects = getProjectOptionsForFile filePath - let project = selectProject projects - - return - project - |> Result.ofOption (fun () -> $"Could not find project containing {filePath}") + and! selectProject = projectSelector + match projects with + | Ok projects -> return selectProject.FindProject(filePath, projects) + | Error e -> return Error e } |> AsyncAVal.forceAsync @@ -1466,7 +1505,8 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let inline tryGetLastCheckResultForFile filePath = checker.TryGetLastCheckResultForFile(filePath) - |> Result.ofOption (fun () -> $"No typecheck results for {filePath}") + |> Result.ofOption (fun () -> + $"No cached typecheck results for {filePath}. This may be ok if the file has not been checked yet.") |> async.Return return @@ -1492,7 +1532,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let allFilesToDeclarations = allFilesParsed - |> AMap.map (fun _k v -> v |> AsyncAVal.mapOption (fun p _ -> p.GetNavigationItems().Declarations)) + |> AMap.map (fun _k v -> v |> AsyncAVal.mapResult (fun p _ -> p.GetNavigationItems().Declarations)) let getAllDeclarations () = async { @@ -1503,15 +1543,18 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac |> Array.map (fun (k, v) -> async { let! decls = AsyncAVal.forceAsync v - return Option.map (fun v -> k, v) decls + return Result.map (fun v -> k, v) decls }) |> Async.parallel75 - return results |> Array.Parallel.choose id + let results = results |> Array.choose (Result.toOption) + return results } - let getDeclarations filename = allFilesToDeclarations |> AMapAsync.tryFindAndFlatten filename + let getDeclarations filename = + allFilesToDeclarations + |> AMapAsync.tryFindAndFlattenR $"Could not find getDeclarations for {filename}" filename @@ -1590,9 +1633,12 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let getProjectOptions file = async { let! projects = getProjectOptionsForFile file |> AsyncAVal.forceAsync + let selectProject = projectSelector |> AVal.force return - selectProject projects + projects + |> Result.bind (fun p -> selectProject.FindProject(file, p)) + |> Result.toOption |> Option.map (fun project -> project.FSharpProjectOptions) } @@ -1600,6 +1646,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let projectsThatContainFile file = async { let! projects = getProjectOptionsForFile file |> AsyncAVal.forceAsync + let projects = projects |> Result.toOption |> Option.defaultValue [] return projects |> List.map (fun p -> p.FSharpProjectOptions) } @@ -1812,6 +1859,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let isOutsideWorkspace (file: string) = asyncAVal { let! rootPath = rootPath + and! selectProject = projectSelector match rootPath with | None -> return true // no root workspace specified @@ -1832,9 +1880,12 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac else let! projectOptions = getProjectOptionsForFile file - match projectOptions |> selectProject with - | None -> return true - | Some projectOptions -> + match + projectOptions + |> Result.bind (fun projs -> selectProject.FindProject(file, projs)) + with + | Error _ -> return true + | Ok projectOptions -> if doesNotExist (UMX.tag projectOptions.ProjectFileName) then return true // script file else @@ -1857,6 +1908,10 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac textChanges.Remove filePath |> ignore) + // Flush changes to the adaptive system so they can remove the file from their cache + let! _ = forceGetOpenFileTypeCheckResults filePath + let! _ = forceGetOpenFileTypeCheckResultsStale filePath + let! isOutsideWorkspace = isOutsideWorkspace filePath if doesNotExist filePath || isOutsideWorkspace then @@ -1877,6 +1932,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let getDependentFilesForFile file = async { let! projects = getProjectOptionsForFile file |> AsyncAVal.forceAsync + let projects = projects |> Result.toOption |> Option.defaultValue [] return projects @@ -1904,6 +1960,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let! dependentFiles = getDependentFilesForFile filePath let! projs = getProjectOptionsForFile filePath |> AsyncAVal.forceAsync + let projs = projs |> Result.toOption |> Option.defaultValue [] let dependentProjects = projs @@ -1935,10 +1992,7 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac |> Array.map (fun (proj, file) -> let file = UMX.tag file - let token = - tryGetOpenFileToken filePath - |> Option.map (fun cts -> cts.Token) - |> Option.defaultWith (fun () -> CancellationToken.None) + let token = getOpenFileTokenOrDefault filePath bypassAdaptiveTypeCheck (file) (proj) |> Async.withCancellation token diff --git a/src/FsAutoComplete/LspServers/AdaptiveServerState.fsi b/src/FsAutoComplete/LspServers/AdaptiveServerState.fsi index 53280cdc4..3ed4e9ebf 100644 --- a/src/FsAutoComplete/LspServers/AdaptiveServerState.fsi +++ b/src/FsAutoComplete/LspServers/AdaptiveServerState.fsi @@ -115,7 +115,7 @@ type AdaptiveState = member GetDeclarationLocation: symbolUse: FSharpSymbolUse * text: IFSACSourceText -> Async> - member GetDeclarations: filename: string -> Async + member GetDeclarations: filename: string -> Async> member GetAllDeclarations: unit -> Async<(string * NavigationTopLevelDeclaration array) array> member GlyphToSymbolKind: (FSharpGlyph -> SymbolKind option) interface IDisposable