From e4c242ccb44501767bb414996aba85a9ce5ebd29 Mon Sep 17 00:00:00 2001 From: Bronson Bata Date: Thu, 16 Nov 2023 08:28:16 -0600 Subject: [PATCH 1/2] Ran `dotnet paket simplify` (#1204) --- benchmarks/paket.references | 3 +-- build/paket.references | 27 +++++++------------ paket.dependencies | 10 ------- src/FsAutoComplete.Core/paket.references | 7 +---- src/FsAutoComplete/paket.references | 9 +------ .../FsAutoComplete.Tests.Lsp/paket.references | 10 +++---- test/OptionAnalyzer/paket.references | 3 +-- 7 files changed, 18 insertions(+), 51 deletions(-) diff --git a/benchmarks/paket.references b/benchmarks/paket.references index d29cc1cf0..50f1157c9 100644 --- a/benchmarks/paket.references +++ b/benchmarks/paket.references @@ -1,4 +1,3 @@ -FSharp.Core BenchmarkDotNet Microsoft.CodeAnalysis -FSharp.Data.Adaptive +FSharp.Data.Adaptive \ No newline at end of file diff --git a/build/paket.references b/build/paket.references index aa0513d00..76fa44de9 100644 --- a/build/paket.references +++ b/build/paket.references @@ -1,18 +1,11 @@ group Build - Fake.Core.Target - Fake.Core.Process - Fake.DotNet.Cli - Fake.Core.ReleaseNotes - Fake.DotNet.AssemblyInfoFile - Fake.DotNet.Paket - Fake.Tools.Git - Fake.Core.Environment - Fake.Core.UserInput - Fake.IO.FileSystem - Fake.IO.Zip - Fake.DotNet.MsBuild - Fake.Api.GitHub - Microsoft.Build - MSBuild.StructuredLogger - Octokit - Fantomas.Core +Fake.Core.Target +Fake.Core.ReleaseNotes +Fake.DotNet.AssemblyInfoFile +Fake.DotNet.Paket +Fake.Tools.Git +Fake.Core.UserInput +Fake.IO.Zip +Fake.Api.GitHub +Microsoft.Build +Fantomas.Core \ No newline at end of file diff --git a/paket.dependencies b/paket.dependencies index 39be78fc6..4328f2285 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -27,9 +27,7 @@ nuget Microsoft.CodeAnalysis 4.5.0 nuget FSharp.Analyzers.SDK nuget ICSharpCode.Decompiler nuget Mono.Cecil >= 0.11.4 -nuget Newtonsoft.Json nuget FSharpLint.Core -nuget System.Configuration.ConfigurationManager nuget Serilog >= 2.10.0 nuget Serilog.Sinks.File >= 5.0.0 nuget Serilog.Sinks.Console >= 4.0.0 @@ -48,7 +46,6 @@ nuget Dotnet.ReproducibleBuilds copy_local:true nuget Microsoft.NETFramework.ReferenceAssemblies nuget Ionide.KeepAChangelog.Tasks copy_local: true -nuget Expecto nuget Expecto.Diff nuget YoloDev.Expecto.TestSdk nuget AltCover @@ -69,24 +66,17 @@ group Build framework: net6.0, net7.0 nuget Fake.Core.Target - nuget Fake.Core.Process - nuget Fake.DotNet.Cli nuget Fake.Core.ReleaseNotes nuget Fake.DotNet.AssemblyInfoFile nuget Fake.DotNet.Paket nuget Fake.Tools.Git - nuget Fake.Core.Environment nuget Fake.Core.UserInput - nuget Fake.IO.FileSystem nuget Fake.IO.Zip - nuget Fake.DotNet.MsBuild nuget Fake.Api.GitHub nuget Microsoft.Build - nuget MSBuild.StructuredLogger nuget Octokit 0.48 // there's an API break in 0.50, so we need to pin this to prevent errors nuget Fantomas.Core 6.2.0 nuget NuGet.Versioning 6.7.0 nuget NuGet.Common 6.7.0 nuget NuGet.Protocol 6.7.0 - diff --git a/src/FsAutoComplete.Core/paket.references b/src/FsAutoComplete.Core/paket.references index 12fbc304d..f67d19aba 100644 --- a/src/FsAutoComplete.Core/paket.references +++ b/src/FsAutoComplete.Core/paket.references @@ -1,21 +1,16 @@ -FSharp.Compiler.Service FSharp.Analyzers.SDK -Newtonsoft.Json ICSharpCode.Decompiler Microsoft.SourceLink.GitHub -System.Configuration.ConfigurationManager FSharp.UMX FsToolkit.ErrorHandling.TaskResult Fantomas.Client FSharp.Data.Adaptive IcedTasks - Ionide.ProjInfo.ProjectSystem -System.Reflection.Metadata Microsoft.Build.Utilities.Core Ionide.LanguageServerProtocol Ionide.KeepAChangelog.Tasks Microsoft.Extensions.Caching.Memory Microsoft.CodeAnalysis LinkDotNet.StringBuilder -CommunityToolkit.HighPerformance +CommunityToolkit.HighPerformance \ No newline at end of file diff --git a/src/FsAutoComplete/paket.references b/src/FsAutoComplete/paket.references index 29b7a6a7a..e5a7e948f 100644 --- a/src/FsAutoComplete/paket.references +++ b/src/FsAutoComplete/paket.references @@ -1,12 +1,8 @@ -#FSharpLint.Core CliWrap Destructurama.FSharp Fantomas.Client FSharp.Analyzers.SDK -FSharp.Compiler.Service -FSharp.Core FSharp.UMX -FsToolkit.ErrorHandling FsToolkit.ErrorHandling.TaskResult IcedTasks ICSharpCode.Decompiler @@ -15,16 +11,13 @@ Ionide.LanguageServerProtocol Ionide.ProjInfo.ProjectSystem Microsoft.NETFramework.ReferenceAssemblies Microsoft.SourceLink.GitHub -Newtonsoft.Json -Serilog Serilog.Sinks.Async Serilog.Sinks.Console Serilog.Sinks.File System.CommandLine -System.Configuration.ConfigurationManager FSharp.Data.Adaptive Microsoft.Extensions.Caching.Memory OpenTelemetry.Exporter.OpenTelemetryProtocol Microsoft.CodeAnalysis LinkDotNet.StringBuilder -CommunityToolkit.HighPerformance +CommunityToolkit.HighPerformance \ No newline at end of file diff --git a/test/FsAutoComplete.Tests.Lsp/paket.references b/test/FsAutoComplete.Tests.Lsp/paket.references index 0696c0d64..dd52fd1a2 100644 --- a/test/FsAutoComplete.Tests.Lsp/paket.references +++ b/test/FsAutoComplete.Tests.Lsp/paket.references @@ -2,7 +2,6 @@ FSharp.Core content: once FSharp.Compiler.Service FSharp.Control.Reactive FSharpx.Async -Expecto Expecto.Diff Microsoft.NET.Test.Sdk YoloDev.Expecto.TestSdk @@ -10,9 +9,8 @@ AltCover GitHubActionsTestLogger CliWrap FSharp.Data.Adaptive - -Microsoft.Build copy_local:false -Microsoft.Build.Framework copy_local:false -Microsoft.Build.Utilities.Core copy_local:false +Microsoft.Build copy_local: false +Microsoft.Build.Framework copy_local: false +Microsoft.Build.Utilities.Core copy_local: false Microsoft.Build.Tasks.Core copy_local: false -NuGet.Frameworks copy_local: false +NuGet.Frameworks copy_local: false \ No newline at end of file diff --git a/test/OptionAnalyzer/paket.references b/test/OptionAnalyzer/paket.references index 3e2eb776c..313894ee0 100644 --- a/test/OptionAnalyzer/paket.references +++ b/test/OptionAnalyzer/paket.references @@ -1,2 +1 @@ -FSharp.Core -FSharp.Analyzers.Sdk +FSharp.Analyzers.Sdk \ No newline at end of file From ee6526744668ca1d3268128727f727523742bc40 Mon Sep 17 00:00:00 2001 From: Paulmichael Blasucci Date: Thu, 16 Nov 2023 15:31:41 +0100 Subject: [PATCH 2/2] Results of Amplifying F# Sesssion (#1195) * Results of Amplifying F# Sesssion Co-authored-by: Jimmy Byrd * Replaces spurious hover errors with log messages * Similar treatment for certain helper functions * Basic test for pipeline hints (needs more coverage) * Fantomas --- src/FsAutoComplete.Core/Commands.fs | 8 +-- .../ParseAndCheckResults.fs | 53 +++++++++----- .../ParseAndCheckResults.fsi | 4 +- .../LspServers/AdaptiveFSharpLspServer.fs | 52 +++++++------- .../LspServers/AdaptiveServerState.fs | 7 +- src/FsAutoComplete/LspServers/Common.fs | 22 +++++- .../FsAutoComplete.Tests.Lsp.fsproj | 20 ++---- .../InlineHintsTests.fs | 69 +++++++++++++++++++ test/FsAutoComplete.Tests.Lsp/Program.fs | 1 + 9 files changed, 167 insertions(+), 69 deletions(-) create mode 100644 test/FsAutoComplete.Tests.Lsp/InlineHintsTests.fs diff --git a/src/FsAutoComplete.Core/Commands.fs b/src/FsAutoComplete.Core/Commands.fs index 0130445c6..843143048 100644 --- a/src/FsAutoComplete.Core/Commands.fs +++ b/src/FsAutoComplete.Core/Commands.fs @@ -534,9 +534,7 @@ module Commands = | Error e -> return CoreResponse.ErrorRes e } - let typesig (tyRes: ParseAndCheckResults) (pos: Position) lineStr = - tyRes.TryGetToolTip pos lineStr - |> Result.bimap CoreResponse.Res CoreResponse.ErrorRes + let typesig (tyRes: ParseAndCheckResults) (pos: Position) lineStr = tyRes.TryGetToolTip pos lineStr // Calculates pipeline hints for now as in fSharp/pipelineHint with a bit of formatting on the hints let inlineValues (contents: IFSACSourceText) (tyRes: ParseAndCheckResults) : Async<(pos * String)[]> = @@ -546,7 +544,7 @@ module Commands = option { let! lineStr = contents.GetLine pos - let! tip = tyRes.TryGetToolTip pos lineStr |> Option.ofResult + let! tip = tyRes.TryGetToolTip pos lineStr return TipFormatter.extractGenericParameters tip } @@ -618,7 +616,7 @@ module Commands = option { let! lineStr = contents.GetLine pos - let! tip = tyRes.TryGetToolTip pos lineStr |> Option.ofResult + let! tip = tyRes.TryGetToolTip pos lineStr return TipFormatter.extractGenericParameters tip } diff --git a/src/FsAutoComplete.Core/ParseAndCheckResults.fs b/src/FsAutoComplete.Core/ParseAndCheckResults.fs index d8027aa20..25164017b 100644 --- a/src/FsAutoComplete.Core/ParseAndCheckResults.fs +++ b/src/FsAutoComplete.Core/ParseAndCheckResults.fs @@ -320,7 +320,9 @@ type ParseAndCheckResults member __.TryGetToolTip (pos: Position) (lineStr: LineStr) = match Lexer.findLongIdents (pos.Column, lineStr) with - | None -> ResultOrString.Error "Cannot find ident for tooltip" + | None -> + logger.info (Log.setMessageI $"Cannot find ident for tooltip: {pos.Column:column} in {lineStr:lineString}") + None | Some(col, identIsland) -> let identIsland = Array.toList identIsland // TODO: Display other tooltip types, for example for strings or comments where appropriate @@ -332,15 +334,16 @@ type ParseAndCheckResults match identIsland with | [ ident ] -> match KeywordList.keywordTooltips.TryGetValue ident with - | true, tip -> Ok tip - | _ -> ResultOrString.Error "No tooltip information" - | _ -> ResultOrString.Error "No tooltip information" - | _ -> Ok(tip) - - member x.TryGetToolTipEnhanced - (pos: Position) - (lineStr: LineStr) - : Result, string> = + | true, tip -> Some tip + | _ -> + logger.info (Log.setMessageI $"Cannot find ident for tooltip: {pos.Column:column} in {lineStr:lineString}") + None + | _ -> + logger.info (Log.setMessageI $"Cannot find ident for tooltip: {pos.Column:column} in {lineStr:lineString}") + None + | _ -> Some tip + + member x.TryGetToolTipEnhanced (pos: Position) (lineStr: LineStr) : option = let (|EmptyTooltip|_|) (ToolTipText elems) = match elems with | [] -> Some() @@ -348,11 +351,13 @@ type ParseAndCheckResults | _ -> None match Completion.atPos (pos, x.GetParseResults.ParseTree) with - | Completion.Context.StringLiteral -> Ok None + | Completion.Context.StringLiteral -> None | Completion.Context.SynType | Completion.Context.Unknown -> match Lexer.findLongIdents (pos.Column, lineStr) with - | None -> Error "Cannot find ident for tooltip" + | None -> + logger.info (Log.setMessageI $"Cannot find ident for tooltip: {pos.Column:column} in {lineStr:lineString}") + None | Some(col, identIsland) -> let identIsland = Array.toList identIsland // TODO: Display other tooltip types, for example for strings or comments where appropriate @@ -373,12 +378,20 @@ type ParseAndCheckResults Footer = "" SymbolInfo = TryGetToolTipEnhancedResult.Keyword ident } |> Some - |> Ok - | _ -> Error "No tooltip information" - | _ -> Error "No tooltip information" + | _ -> + logger.info ( + Log.setMessageI $"Cannot find ident for tooltip: {pos.Column:column} in {lineStr:lineString}" + ) + + None + | _ -> + logger.info (Log.setMessageI $"Cannot find ident for tooltip: {pos.Column:column} in {lineStr:lineString}") + None | _ -> match symbol with - | None -> Error "No tooltip information" + | None -> + logger.info (Log.setMessageI $"Cannot find ident for tooltip: {pos.Column:column} in {lineStr:lineString}") + None | Some symbol -> // Retrieve the FSharpSymbol instance so we can find the XmlDocSig @@ -388,7 +401,12 @@ type ParseAndCheckResults let resolvedType = symbol.Symbol.GetAbbreviatedParent() match SignatureFormatter.getTooltipDetailsFromSymbolUse symbol with - | None -> Error "No tooltip information" + | None -> + logger.info ( + Log.setMessageI $"Cannot find tooltip for {symbol:symbol} ({pos.Column:column} in {lineStr:lineString})" + ) + + None | Some(signature, footer) -> { ToolTipText = tip Signature = signature @@ -398,7 +416,6 @@ type ParseAndCheckResults {| XmlDocSig = resolvedType.XmlDocSig Assembly = symbol.Symbol.Assembly.SimpleName |} } |> Some - |> Ok member __.TryGetFormattedDocumentation (pos: Position) (lineStr: LineStr) = match Lexer.findLongIdents (pos.Column, lineStr) with diff --git a/src/FsAutoComplete.Core/ParseAndCheckResults.fsi b/src/FsAutoComplete.Core/ParseAndCheckResults.fsi index 73ae4f0dc..f3099f45a 100644 --- a/src/FsAutoComplete.Core/ParseAndCheckResults.fsi +++ b/src/FsAutoComplete.Core/ParseAndCheckResults.fsi @@ -47,9 +47,9 @@ type ParseAndCheckResults = member TryFindIdentifierDeclaration: pos: Position -> lineStr: LineStr -> Async> member TryFindTypeDeclaration: pos: Position -> lineStr: LineStr -> Async> - member TryGetToolTip: pos: Position -> lineStr: LineStr -> Result + member TryGetToolTip: pos: Position -> lineStr: LineStr -> ToolTipText option - member TryGetToolTipEnhanced: pos: Position -> lineStr: LineStr -> Result + member TryGetToolTipEnhanced: pos: Position -> lineStr: LineStr -> TryGetToolTipEnhancedResult option member TryGetFormattedDocumentation: pos: Position -> diff --git a/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs b/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs index 149c6fc3f..574e2cfd7 100644 --- a/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs +++ b/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs @@ -540,7 +540,7 @@ type AdaptiveFSharpLspServer return None // An empty file has empty completions. Otherwise we would error down there else - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr if lineStr.StartsWith("#", StringComparison.Ordinal) then let completionList = @@ -568,7 +568,12 @@ type AdaptiveFSharpLspServer asyncResult { let! volatileFile = state.GetOpenFileOrRead filePath - let! lineStr = volatileFile.Source |> tryGetLineStr pos + + let! lineStr = + volatileFile.Source + |> tryGetLineStr pos + |> Result.mapError ErrorMsgUtils.formatLineLookErr + //TODO ⮝⮝⮝ good candidate for better error model -- review! // TextDocumentCompletion will sometimes come in before TextDocumentDidChange // This will require the trigger character to be at the place VSCode says it is @@ -874,11 +879,11 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResultsCached filePath |> AsyncResult.ofStringErr match tyRes.TryGetToolTipEnhanced pos lineStr with - | Ok(Some tooltipResult) -> + | Some tooltipResult -> logger.info ( Log.setMessage "TryGetToolTipEnhanced : {params}" >> Log.addContextDestructured "params" tooltipResult @@ -939,13 +944,8 @@ type AdaptiveFSharpLspServer | TipFormatter.TipFormatterResult.None -> return None - | Ok(None) -> + | None -> return None - return! LspResult.internalError $"No TryGetToolTipEnhanced results for {filePath}" - | Error e -> - trace.RecordError(e, "TextDocumentHover.Error") |> ignore - logger.error (Log.setMessage "Failed with {error}" >> Log.addContext "error" e) - return! LspResult.internalError e with e -> trace |> Tracing.recordException e @@ -967,7 +967,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr let! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr let! (_, _, range) = @@ -990,7 +990,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr // validate name and surround with backticks if necessary @@ -1064,7 +1064,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr let! decl = tyRes.TryFindDeclaration pos lineStr |> AsyncResult.ofStringErr return decl |> findDeclToLspLocation |> GotoResult.Single |> Some @@ -1094,7 +1094,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr let! decl = tyRes.TryFindTypeDeclaration pos lineStr |> AsyncResult.ofStringErr return decl |> findDeclToLspLocation |> GotoResult.Single |> Some @@ -1123,7 +1123,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.ofStringErr + let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr let! usages = @@ -1159,7 +1159,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.ofStringErr + let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr match @@ -1201,7 +1201,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.ofStringErr + let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr logger.info ( @@ -1560,7 +1560,7 @@ type AdaptiveFSharpLspServer ) let! (sourceText: IFSACSourceText) = state.GetOpenFileSource filePath |> AsyncResult.ofStringErr - let! lineStr = sourceText |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = sourceText |> tryGetLineStr pos |> Result.lineLookupErr let typ = data.[1] let! r = Async.Catch(f arg pos tyRes sourceText lineStr typ filePath) @@ -2071,7 +2071,7 @@ type AdaptiveFSharpLspServer let filePath = Path.FileUriToLocalPath p.Item.Uri |> Utils.normalizePath let pos = protocolPosToPos p.Item.SelectionRange.Start let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.ofStringErr + let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.lineLookupErr // Incoming file may not be "Opened" so we need to force a typecheck let! tyRes = state.GetTypeCheckResultsForFile filePath |> AsyncResult.ofStringErr @@ -2158,7 +2158,7 @@ type AdaptiveFSharpLspServer |> getFilePathAndPosition let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.ofStringErr + let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr let! decl = tyRes.TryFindDeclaration pos lineStr |> AsyncResult.ofStringErr @@ -2240,9 +2240,9 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr - let! tip = Commands.typesig tyRes pos lineStr |> Result.ofCoreResponse + let tip = Commands.typesig tyRes pos lineStr return tip @@ -2275,7 +2275,7 @@ type AdaptiveFSharpLspServer let filePath = p.TextDocument.GetFilePath() |> Utils.normalizePath let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr let! (typ, parms, generics) = tyRes.TryGetSignatureData pos lineStr |> Result.ofStringErr @@ -2311,7 +2311,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr match! @@ -2659,7 +2659,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr match! Commands.Help tyRes pos lineStr |> Result.ofCoreResponse with @@ -2690,7 +2690,7 @@ type AdaptiveFSharpLspServer let (filePath, pos) = getFilePathAndPosition p let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr - let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.ofStringErr + let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr lastFSharpDocumentationTypeCheck <- Some tyRes diff --git a/src/FsAutoComplete/LspServers/AdaptiveServerState.fs b/src/FsAutoComplete/LspServers/AdaptiveServerState.fs index 7bb470fb2..324e42b27 100644 --- a/src/FsAutoComplete/LspServers/AdaptiveServerState.fs +++ b/src/FsAutoComplete/LspServers/AdaptiveServerState.fs @@ -1634,7 +1634,12 @@ type AdaptiveState(lspClient: FSharpLspClient, sourceTextFactory: ISourceTextFac let tryGetParseResultsForFile filePath pos = asyncResult { let! (file) = forceFindOpenFileOrRead filePath - let! lineStr = file.Source |> tryGetLineStr pos + + let! lineStr = + file.Source + |> tryGetLineStr pos + |> Result.mapError ErrorMsgUtils.formatLineLookErr + //TODO ⮝⮝⮝ good candidate for better error model -- review! and! tyRes = forceGetOpenFileTypeCheckResults filePath return tyRes, lineStr, file.Source } diff --git a/src/FsAutoComplete/LspServers/Common.fs b/src/FsAutoComplete/LspServers/Common.fs index 3760274db..bf8d75d79 100644 --- a/src/FsAutoComplete/LspServers/Common.fs +++ b/src/FsAutoComplete/LspServers/Common.fs @@ -14,9 +14,27 @@ open FSharp.UMX open CliWrap +module ErrorMsgUtils = + let formatLineLookErr + (x: + {| FileName: string + Position: FcsPos |}) + = + let position = fcsPosToLsp x.Position + $"No line in {x.FileName} at position {position}" + + module Result = let ofStringErr r = r |> Result.mapError JsonRpc.Error.InternalErrorMessage + let lineLookupErr + (r: + Result<'T, {| FileName: string + Position: FcsPos |}>) + = + r + |> Result.mapError (ErrorMsgUtils.formatLineLookErr >> JsonRpc.Error.InternalErrorMessage) + let ofCoreResponse (r: CoreResponse<'a>) = match r with | CoreResponse.Res a -> Ok(Some a) @@ -186,7 +204,9 @@ module Helpers = let tryGetLineStr pos (text: IFSACSourceText) = text.GetLine(pos) - |> Result.ofOption (fun () -> $"No line in {text.FileName} at position {pos}") + |> Result.ofOption (fun () -> + {| FileName = text.FileName + Position = pos |}) let fullPathNormalized = Path.GetFullPath >> Utils.normalizePath >> UMX.untag diff --git a/test/FsAutoComplete.Tests.Lsp/FsAutoComplete.Tests.Lsp.fsproj b/test/FsAutoComplete.Tests.Lsp/FsAutoComplete.Tests.Lsp.fsproj index dd86a6ba2..72f195aa3 100644 --- a/test/FsAutoComplete.Tests.Lsp/FsAutoComplete.Tests.Lsp.fsproj +++ b/test/FsAutoComplete.Tests.Lsp/FsAutoComplete.Tests.Lsp.fsproj @@ -9,7 +9,6 @@ true true true - @@ -48,27 +47,16 @@ - + - + - - - + + - diff --git a/test/FsAutoComplete.Tests.Lsp/InlineHintsTests.fs b/test/FsAutoComplete.Tests.Lsp/InlineHintsTests.fs new file mode 100644 index 000000000..5f5cc51b5 --- /dev/null +++ b/test/FsAutoComplete.Tests.Lsp/InlineHintsTests.fs @@ -0,0 +1,69 @@ +module FsAutoComplete.Tests.InlineHints + +open Expecto +open Helpers +open Ionide.LanguageServerProtocol.Types +open FsAutoComplete +open Utils.Server +open Utils.Utils +open Utils.TextEdit +open Utils.ServerTests +open Helpers.Expecto.ShadowedTimeouts + +let private testInlineHints (server : CachedServer) text checkResp = + async { + let range, text = + text + |> Text.trimTripleQuotation + |> Cursor.assertExtractRange + + let! (doc, diags) = server |> Server.createUntitledDocument text + use doc = doc + + let inlineValueRequest: InlineValueParams = { + Context = { + FrameId = 0 + StoppedLocation = range + } + Range = range + TextDocument = doc.TextDocumentIdentifier + } + let! resp = doc.Server.Server.TextDocumentInlineValue inlineValueRequest + checkResp resp + } + +let good = """ +let test value = + $0 + value + |> String.replicate 3 + |> String.filter (fun c -> Char.IsAscii(c)) + |> String.length + $0 +value "foo" +""" + +let tests state = + serverTestList "inline hints" state defaultConfigDto None (fun server -> [ + testCaseAsync + "Gets inline hints for simple pipeline" + (testInlineHints + server + good + (fun resp -> + Expect.isOk resp "should get inline hints for valid code fragment" + let resp = resp |> Result.defaultWith (fun _ -> failwith "Unpossible!") + Expect.isSome resp "should get inline hints for valid code fragment" + let resp = resp |> Option.get + Expect.hasLength resp 4 "THERE ARE FOUR LIGHTS!!" + let hints = + resp + |> Array.choose ( + function + | InlineValue.InlineValueText hint -> Some hint.Text + | _ -> None + ) + Expect.containsAll hints [nameof string; nameof int] "should be 3 strings and an int" + ) + ) + ]) diff --git a/test/FsAutoComplete.Tests.Lsp/Program.fs b/test/FsAutoComplete.Tests.Lsp/Program.fs index 9d50b30ed..7444aacd8 100644 --- a/test/FsAutoComplete.Tests.Lsp/Program.fs +++ b/test/FsAutoComplete.Tests.Lsp/Program.fs @@ -96,6 +96,7 @@ let lspTests = analyzerTests createServer signatureTests createServer SignatureHelp.tests createServer + InlineHints.tests createServer CodeFixTests.Tests.tests sourceTextFactory createServer Completion.tests createServer GoTo.tests createServer