From 452411b75d626b78698f7cd1aef6591da9d08bda Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Mon, 21 Aug 2023 11:01:27 -0500 Subject: [PATCH] Update to 7.0.4xx FCS versions (#1151) Co-authored-by: Maxime Mangel Co-authored-by: github-actions Co-authored-by: Maxime Mangel Co-authored-by: Florian Verdonck Co-authored-by: dawe --- .github/workflows/build-and-pack-nightly.yml | 34 + .vscode/settings.json | 44 +- Directory.Build.targets | 12 + build/Program.fs | 19 +- paket.dependencies | 45 +- paket.lock | 80 +- src/FsAutoComplete.Core/Commands.fs | 116 +- .../CompilerServiceInterface.fs | 13 +- .../CompilerServiceInterface.fsi | 4 +- src/FsAutoComplete.Core/InlayHints.fs | 2 +- src/FsAutoComplete.Core/Lexer.fs | 31 +- .../ParseAndCheckResults.fs | 7 + .../ParseAndCheckResults.fsi | 2 + src/FsAutoComplete.Core/State.fs | 7 +- .../UnionPatternMatchCaseGenerator.fs | 2 +- src/FsAutoComplete.Core/UntypedAstUtils.fs | 12 +- .../CodeFixes/AddMissingXmlDocumentation.fs | 39 +- .../CodeFixes/AddPrivateAccessModifier.fs | 5 +- .../CodeFixes/AddPrivateAccessModifier.fsi | 3 +- ...ConvertTripleSlashCommentToXmlTaggedDoc.fs | 4 +- .../CodeFixes/RenameUnusedValue.fs | 33 +- src/FsAutoComplete/LspHelpers.fs | 14 +- src/FsAutoComplete/LspHelpers.fsi | 3 + .../LspServers/AdaptiveFSharpLspServer.fs | 52 +- .../LspServers/FsAutoComplete.Lsp.fs | 12 +- src/FsAutoComplete/paket.references | 2 +- .../CodeFixTests/Tests.fs | 1180 ++++++++++------- 27 files changed, 1085 insertions(+), 692 deletions(-) create mode 100644 .github/workflows/build-and-pack-nightly.yml create mode 100644 Directory.Build.targets diff --git a/.github/workflows/build-and-pack-nightly.yml b/.github/workflows/build-and-pack-nightly.yml new file mode 100644 index 000000000..d6a3c4717 --- /dev/null +++ b/.github/workflows/build-and-pack-nightly.yml @@ -0,0 +1,34 @@ +name: Build and pack nightly + +on: + push: + branches: + - nightly + +env: + BuildNet7: true + +jobs: + pack-nightly: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Get date for version + id: date + run: echo "::set-output name=date::$(date +'%Y%m%d%H%M')" + # setup .NET per the repo global.json + - name: Setup .NET + uses: actions/setup-dotnet@v2 + + - name: Restore tools + run: dotnet tool restore + + - name: Run Build + run: dotnet run --project build -t Release + env: + VersionSuffix: "beta${{ steps.date.outputs.date }}" + + - name: Push packages + run: dotnet nuget push bin/pkgs/fsautocomplete.*.nupkg --source https://nuget.pkg.github.com/fsharp/index.json --api-key ${{ secrets.GITHUB_TOKEN }} diff --git a/.vscode/settings.json b/.vscode/settings.json index 0b796aa11..bd975e647 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,23 +1,23 @@ { - "FSharp.excludeProjectDirectories": [ - ".git", - "paket-files", - "packages", - "test/FsAutoComplete.IntegrationTests" - ], - //otherwise take a lot of time to load proj inside - //the test directories - "omnisharp.autoStart": false, - "FSharp.minimizeBackgroundParsing": true, - "FSharp.trace.server": "verbose", - "yaml.schemas": { - "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-workflow.json": ".github/workflows/*" - }, - "editor.inlayHints.enabled": "offUnlessPressed", - "FSharp.enableAdaptiveLspServer": true, - "files.associations": { - "*.*proj": "msbuild", - "*.props": "msbuild", - "*.targets": "msbuild" - } -} + "FSharp.excludeProjectDirectories": [ + ".git", + "paket-files", + "packages", + "test/FsAutoComplete.IntegrationTests" + ], + //otherwise take a lot of time to load proj inside + //the test directories + "omnisharp.autoStart": false, + "FSharp.minimizeBackgroundParsing": true, + "FSharp.trace.server": "off", + "yaml.schemas": { + "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-workflow.json": ".github/workflows/*" + }, + "editor.inlayHints.enabled": "offUnlessPressed", + "FSharp.enableAdaptiveLspServer": true, + "files.associations": { + "*.*proj": "msbuild", + "*.props": "msbuild", + "*.targets": "msbuild" + } +} \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 000000000..ac86c2874 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,12 @@ + + + + + $(Version)-$(VersionSuffix) + $(Version) + + + + + diff --git a/build/Program.fs b/build/Program.fs index 719dfccbc..9584e62ca 100644 --- a/build/Program.fs +++ b/build/Program.fs @@ -18,6 +18,7 @@ let configuration = Environment.environVarOrDefault "configuration" "Release" let buildDir = "src" project "bin" "Debug" let buildReleaseDir = "src" project "bin" "Release" let pkgsDir = "bin" "pkgs" +let toolsDir = "bin" "release_as_tool" let releaseArchiveNetCore = pkgsDir "fsautocomplete.netcore.zip" // Files to format @@ -74,25 +75,24 @@ let init args = failwithf "Errors while generating coverage report: %A" r.Errors) Target.create "ReleaseArchive" (fun _ -> - Shell.cleanDirs [ "bin/pkgs" ] - Directory.ensure "bin/pkgs" + Directory.ensure pkgsDir - !!(sprintf "bin/release_as_tool/fsautocomplete.%s.nupkg" currentRelease.AssemblyVersion) - |> Shell.copy "bin/pkgs") + !!(toolsDir "fsautocomplete.*.nupkg") + |> Shell.copy pkgsDir) Target.create "LocalRelease" (fun _ -> - Directory.ensure "bin/release_as_tool" - Shell.cleanDirs [ "bin/release_as_tool" ] + Directory.ensure toolsDir + Shell.cleanDirs [ toolsDir ] DotNet.pack (fun p -> { p with - OutputPath = Some(__SOURCE_DIRECTORY__ ".." "bin/release_as_tool") + OutputPath = Some(__SOURCE_DIRECTORY__ ".." toolsDir) Configuration = DotNet.BuildConfiguration.fromString configuration MSBuildParams = { MSBuild.CliArguments.Create() with Properties = [ packAsToolProp ] } }) "src/FsAutoComplete") - Target.create "Clean" (fun _ -> Shell.cleanDirs [ buildDir; buildReleaseDir; pkgsDir ]) + Target.create "Clean" (fun _ -> Shell.cleanDirs [ buildDir; buildReleaseDir; pkgsDir; toolsDir ]) Target.create "Restore" (fun _ -> DotNet.restore id "") @@ -178,7 +178,8 @@ let init args = "Build" ==> "LspTest" ==> "Coverage" ==> "Test" ==> "All" |> ignore - "LocalRelease" + "Clean" + ==> "LocalRelease" ==> "ReleaseArchive" ==> "Release" |> ignore diff --git a/paket.dependencies b/paket.dependencies index f0eeb9edb..e34f8d8f7 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -4,7 +4,7 @@ framework: netstandard2.0, netstandard2.1, net6.0, net7.0 source https://api.nuget.org/v3/index.json # this is the FCS nightly feed, re-enable at your own risk! -#source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json +#source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json #source: ./libs storage: none strategy: min @@ -13,37 +13,37 @@ lowest_matching: true nuget BenchmarkDotNet 0.13.5 nuget Fantomas.Client >= 0.9 -nuget FSharp.Compiler.Service >= 43.7.300 -nuget Ionide.ProjInfo >= 0.61.3 -nuget Ionide.ProjInfo.FCS >= 0.61.3 -nuget Ionide.ProjInfo.ProjectSystem >= 0.61.3 -nuget Ionide.ProjInfo.Sln >= 0.61.3 +nuget FSharp.Compiler.Service >= 43.7.400 +nuget Ionide.ProjInfo >= 0.62.0 +nuget Ionide.ProjInfo.FCS >= 0.62.0 +nuget Ionide.ProjInfo.ProjectSystem >= 0.62.0 +nuget Ionide.ProjInfo.Sln >= 0.62.0 nuget Microsoft.Build >= 17.2 copy_local:false nuget Microsoft.Build.Framework >= 17.4 copy_local:false nuget Microsoft.Build.Utilities.Core >= 17.4 copy_local:false nuget Microsoft.Build.Tasks.Core >= 17.4 copy_local: false +nuget Nuget.Frameworks >= 6.3 copy_local: false nuget Microsoft.CodeAnalysis 4.5.0 -nuget Nuget.Frameworks copy_local: false nuget FSharp.Analyzers.SDK nuget ICSharpCode.Decompiler -nuget Mono.Cecil +nuget Mono.Cecil >= 0.11.4 nuget Newtonsoft.Json nuget FSharpLint.Core nuget System.Configuration.ConfigurationManager -nuget Serilog -nuget Serilog.Sinks.File -nuget Serilog.Sinks.Console -nuget Serilog.Sinks.Async +nuget Serilog >= 2.10.0 +nuget Serilog.Sinks.File >= 5.0.0 +nuget Serilog.Sinks.Console >= 4.0.0 +nuget Serilog.Sinks.Async >= 1.5 nuget Destructurama.FSharp -nuget FSharp.UMX -nuget FSharp.Formatting -nuget FsToolkit.ErrorHandling.TaskResult framework: netstandard2.1 ,net6.0, net7.0 -nuget IcedTasks -nuget FSharpx.Async -nuget CliWrap +nuget FSharp.UMX >= 1.1 +nuget FSharp.Formatting >= 14.0 +nuget FsToolkit.ErrorHandling.TaskResult >= 4.4 framework: netstandard2.1 ,net6.0, net7.0 +nuget IcedTasks >= 0.5 +nuget FSharpx.Async >= 1.14 +nuget CliWrap >= 3.0 nuget System.CommandLine prerelease -nuget FSharp.Data.Adaptive -nuget Microsoft.NET.Test.Sdk +nuget FSharp.Data.Adaptive >= 1.2 +nuget Microsoft.NET.Test.Sdk >= 17.4 nuget Dotnet.ReproducibleBuilds copy_local:true nuget Microsoft.NETFramework.ReferenceAssemblies @@ -55,12 +55,11 @@ nuget AltCover nuget GitHubActionsTestLogger nuget Ionide.LanguageServerProtocol >= 0.4.16 nuget Microsoft.Extensions.Caching.Memory -nuget OpenTelemetry.Exporter.OpenTelemetryProtocol >= 1.3.2 +nuget OpenTelemetry.Api >= 1.3.2 +nuget OpenTelemetry.Exporter.OpenTelemetryProtocol >= 1.3.2 # 1.4 bumps to 7.0 versions of System.Diagnostics libs, so can't use it nuget LinkDotNet.StringBuilder 1.18.0 nuget CommunityToolkit.HighPerformance - - group Build source https://api.nuget.org/v3/index.json storage: none diff --git a/paket.lock b/paket.lock index 163da37fa..5e908fc45 100644 --- a/paket.lock +++ b/paket.lock @@ -59,14 +59,14 @@ NUGET FSharp.Compiler.Service (>= 41.0.1) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net5.0)) (&& (== netstandard2.1) (>= net5.0)) FSharp.Core (>= 6.0.1) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net5.0)) (&& (== netstandard2.1) (>= net5.0)) McMaster.NETCore.Plugins (>= 1.4) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net5.0)) (&& (== netstandard2.1) (>= net5.0)) - FSharp.Compiler.Service (43.7.300) - FSharp.Core (7.0.300) + FSharp.Compiler.Service (43.7.400) + FSharp.Core (7.0.400) System.Buffers (>= 4.5.1) - System.Collections.Immutable (>= 6.0) - System.Diagnostics.DiagnosticSource (>= 6.0) + System.Collections.Immutable (>= 7.0) + System.Diagnostics.DiagnosticSource (>= 7.0.2) System.Memory (>= 4.5.5) System.Reflection.Emit (>= 4.7) - System.Reflection.Metadata (>= 6.0.1) + System.Reflection.Metadata (>= 7.0) System.Runtime.CompilerServices.Unsafe (>= 6.0) FSharp.Control.AsyncSeq (3.2.1) FSharp.Core (>= 4.7.2) @@ -74,7 +74,7 @@ NUGET FSharp.Control.Reactive (5.0.5) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) FSharp.Core (>= 4.7.2) System.Reactive (>= 5.0 < 6.0) - FSharp.Core (7.0.300) + FSharp.Core (7.0.400) FSharp.Data.Adaptive (1.2.13) FSharp.Core (>= 4.7) System.Reflection.Emit.Lightweight (>= 4.6) @@ -123,7 +123,7 @@ NUGET Grpc.Core.Api (>= 2.51) Humanizer.Core (2.14.1) Iced (1.17) - IcedTasks (0.5.3) + IcedTasks (0.5.4) FSharp.Core (>= 7.0) ICSharpCode.Decompiler (7.2.1.6856) Microsoft.Win32.Registry (>= 5.0) @@ -134,25 +134,25 @@ NUGET FSharp.Core (>= 6.0) Newtonsoft.Json (>= 13.0.1) StreamJsonRpc (>= 2.10.44) - Ionide.ProjInfo (0.61.3) - FSharp.Core (>= 6.0.5) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.Sln (>= 0.61.3) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo (0.62) + FSharp.Core (>= 7.0.400) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo.Sln (>= 0.62) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) Microsoft.Build (>= 17.2) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) Microsoft.Build.Framework (>= 17.2) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) SemanticVersioning (>= 2.0.2) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.FCS (0.61.3) - FSharp.Compiler.Service (>= 41.0.5) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - FSharp.Core (>= 6.0.5) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo (>= 0.61.3) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.ProjectSystem (0.61.3) - FSharp.Compiler.Service (>= 41.0.5) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo.FCS (0.62) + FSharp.Compiler.Service (>= 43.7.400) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + FSharp.Core (>= 7.0.400) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo (>= 0.62) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo.ProjectSystem (0.62) + FSharp.Compiler.Service (>= 43.7.400) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) FSharp.Control.Reactive (>= 5.0.5) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - FSharp.Core (>= 6.0.5) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo (>= 0.61.3) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.FCS (>= 0.61.3) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.Sln (>= 0.61.3) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + FSharp.Core (>= 7.0.400) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo (>= 0.62) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo.FCS (>= 0.62) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Ionide.ProjInfo.Sln (>= 0.62) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) Newtonsoft.Json (>= 13.0.1) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.Sln (0.61.3) + Ionide.ProjInfo.Sln (0.62) LinkDotNet.StringBuilder (1.18) McMaster.NETCore.Plugins (1.4) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net5.0)) (&& (== netstandard2.1) (>= net5.0)) Microsoft.DotNet.PlatformAbstractions (>= 3.1.6) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) @@ -180,9 +180,10 @@ NUGET System.Text.Encoding.CodePages (>= 4.0.1) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) System.Text.Json (>= 6.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net472)) (&& (== netstandard2.1) (>= net6.0)) System.Threading.Tasks.Dataflow (>= 6.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net472)) (&& (== netstandard2.1) (>= net6.0)) - Microsoft.Build.Framework (17.4) - copy_local: false + Microsoft.Build.Framework (17.6.3) - copy_local: false Microsoft.Win32.Registry (>= 5.0) - restriction: || (== net6.0) (== netstandard2.0) (== netstandard2.1) - System.Security.Permissions (>= 6.0) + System.Security.Permissions (>= 7.0) + System.Security.Principal.Windows (>= 5.0) - restriction: || (== net6.0) (== netstandard2.0) (== netstandard2.1) Microsoft.Build.Locator (1.5.3) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net5.0)) (&& (== netstandard2.1) (>= net5.0)) Microsoft.Build.Tasks.Core (17.4) - copy_local: false Microsoft.Build.Framework (>= 17.4) @@ -349,7 +350,7 @@ NUGET System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (< netcoreapp2.0)) (&& (== net6.0) (< netcoreapp2.1)) (&& (== net6.0) (>= uap10.1)) (&& (== net7.0) (< netcoreapp2.0)) (&& (== net7.0) (< netcoreapp2.1)) (&& (== net7.0) (>= uap10.1)) (== netstandard2.0) (== netstandard2.1) System.Security.AccessControl (>= 5.0) System.Security.Principal.Windows (>= 5.0) - Microsoft.Win32.SystemEvents (6.0.1) - copy_local: false, restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) + Microsoft.Win32.SystemEvents (7.0) - copy_local: false, restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) Mono.Cecil (0.11.4) Nerdbank.Streams (2.8.61) Microsoft.Bcl.AsyncInterfaces (>= 5.0) @@ -395,9 +396,9 @@ NUGET System.Threading.Tasks.Dataflow (>= 6.0) System.Buffers (4.5.1) System.CodeDom (6.0) - copy_local: false - System.Collections.Immutable (6.0) - System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) - System.Runtime.CompilerServices.Unsafe (>= 6.0) + System.Collections.Immutable (7.0) + System.Memory (>= 4.5.5) - restriction: || (&& (== net6.0) (>= net462)) (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) + System.Runtime.CompilerServices.Unsafe (>= 6.0) - restriction: || (== net6.0) (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) System.CommandLine (2.0.0-beta4.22272.1) System.Memory (>= 4.5.4) - restriction: || (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) System.ComponentModel.Annotations (5.0) - restriction: || (&& (== net6.0) (< netstandard2.1)) (&& (== net7.0) (< netstandard2.1)) (== netstandard2.0) @@ -420,11 +421,11 @@ NUGET System.Configuration.ConfigurationManager (6.0) System.Security.Cryptography.ProtectedData (>= 6.0) System.Security.Permissions (>= 6.0) - System.Diagnostics.DiagnosticSource (6.0) - System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net6.0) (< net5.0)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< net5.0)) (== netstandard2.0) (== netstandard2.1) - System.Runtime.CompilerServices.Unsafe (>= 6.0) - System.Drawing.Common (6.0) - copy_local: false, restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) - Microsoft.Win32.SystemEvents (>= 6.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) + System.Diagnostics.DiagnosticSource (7.0.2) + System.Memory (>= 4.5.5) - restriction: || (&& (== net6.0) (>= net462)) (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) + System.Runtime.CompilerServices.Unsafe (>= 6.0) - restriction: || (== net6.0) (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) + System.Drawing.Common (7.0) - copy_local: false, restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + Microsoft.Win32.SystemEvents (>= 7.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) System.Formats.Asn1 (6.0) - copy_local: false System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) @@ -445,8 +446,9 @@ NUGET System.Reflection.Emit.ILGeneration (4.7) - restriction: || (&& (== net7.0) (< netcoreapp2.0) (< netstandard2.1)) (&& (== net7.0) (< netstandard1.1)) (&& (== net7.0) (< netstandard2.0)) (&& (== net7.0) (>= uap10.1)) (== netstandard2.0) (&& (== netstandard2.1) (< netstandard1.1)) (&& (== netstandard2.1) (< netstandard2.0)) (&& (== netstandard2.1) (>= uap10.1)) System.Reflection.Emit.Lightweight (4.7) System.Reflection.Emit.ILGeneration (>= 4.7) - restriction: || (&& (== net6.0) (< netcoreapp2.0) (< netstandard2.1)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (< portable-net45+wp8)) (&& (== net6.0) (>= uap10.1)) (&& (== net7.0) (< netcoreapp2.0) (< netstandard2.1)) (&& (== net7.0) (< netstandard2.0)) (&& (== net7.0) (< portable-net45+wp8)) (&& (== net7.0) (>= uap10.1)) (== netstandard2.0) (&& (== netstandard2.1) (< netstandard2.0)) (&& (== netstandard2.1) (< portable-net45+wp8)) (&& (== netstandard2.1) (>= uap10.1)) - System.Reflection.Metadata (6.0.1) - System.Collections.Immutable (>= 6.0) + System.Reflection.Metadata (7.0) + System.Collections.Immutable (>= 7.0) + System.Memory (>= 4.5.5) - restriction: || (&& (== net6.0) (>= net462)) (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) System.Resources.Extensions (6.0) - copy_local: false System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) System.Runtime.CompilerServices.Unsafe (6.0) @@ -464,9 +466,9 @@ NUGET System.Memory (>= 4.5.4) - restriction: || (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) System.Security.AccessControl (>= 6.0) System.Security.Cryptography.Pkcs (>= 6.0.1) - System.Security.Permissions (6.0) - copy_local: false - System.Security.AccessControl (>= 6.0) - System.Windows.Extensions (>= 6.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) + System.Security.Permissions (7.0) - copy_local: false + System.Security.AccessControl (>= 6.0) - restriction: || (&& (== net6.0) (>= net462)) (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0) (== netstandard2.1) + System.Windows.Extensions (>= 7.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) System.Security.Principal.Windows (5.0) - copy_local: false System.Text.Encoding.CodePages (6.0) - copy_local: false System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netcoreapp3.1)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0) (== netstandard2.1) @@ -481,8 +483,8 @@ NUGET System.Threading.Tasks.Dataflow (6.0) - copy_local: false System.Threading.Tasks.Extensions (4.5.4) System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netcoreapp2.1)) (&& (== net6.0) (< netstandard1.0)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (>= wp8)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp2.1)) (&& (== net7.0) (< netstandard1.0)) (&& (== net7.0) (< netstandard2.0)) (&& (== net7.0) (>= wp8)) (== netstandard2.0) (== netstandard2.1) - System.Windows.Extensions (6.0) - copy_local: false, restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) - System.Drawing.Common (>= 6.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) + System.Windows.Extensions (7.0) - copy_local: false, restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) + System.Drawing.Common (>= 7.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) YoloDev.Expecto.TestSdk (0.13.3) Expecto (>= 9.0 < 10.0) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) FSharp.Core (>= 4.6.2) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= netcoreapp3.1)) (&& (== netstandard2.1) (>= netcoreapp3.1)) diff --git a/src/FsAutoComplete.Core/Commands.fs b/src/FsAutoComplete.Core/Commands.fs index 424fea740..10eb5cea2 100644 --- a/src/FsAutoComplete.Core/Commands.fs +++ b/src/FsAutoComplete.Core/Commands.fs @@ -740,25 +740,7 @@ module Commands = Position = pos Scope = ic.ScopeKind })) - /// * `includeDeclarations`: - /// if `false` only returns usage locations and excludes declarations - /// * Note: if `true` you can still separate usages and declarations from each other - /// with `Symbol.partitionInfoDeclarationsAndUsages` - /// * `includeBackticks`: - /// if `true` returns ranges including existing backticks, otherwise without: - /// `let _ = ``my value`` + 42` - /// * `true`: ` ``my value`` ` - /// * `false`: `my value` - /// * `errorOnFailureToFixRange`: - /// Ranges returned by FCS don't just span the actual identifier, but include Namespace, Module, Type: `System.String.IsNullOrEmpty` - /// These ranges gets adjusted to include just the concrete identifier (`IsNullOrEmpty`) - /// * If `false` and range cannot be adjust, the original range gets used. - /// * When results are more important than always exact range - /// -> for "Find All References" - /// * If `true`: Instead of using the source range, this function instead returns an Error - /// * When exact ranges are required - /// -> for "Rename" - let symbolUseWorkspace + let symbolUseWorkspaceAux (getDeclarationLocation: FSharpSymbolUse * IFSACSourceText -> Async) (findReferencesForSymbolInFile: (string * FSharpProjectOptions * FSharpSymbol) -> Async) (tryGetFileSource: string -> Async>) @@ -767,13 +749,11 @@ module Commands = (includeDeclarations: bool) (includeBackticks: bool) (errorOnFailureToFixRange: bool) - pos - lineStr (text: IFSACSourceText) (tyRes: ParseAndCheckResults) + (symbolUse: FSharpSymbolUse) : Async, Range[]>), string>> = asyncResult { - let! symbolUse = tyRes.TryGetSymbolUse pos lineStr |> Result.ofOption (fun _ -> "No symbol") let symbol = symbolUse.Symbol let symbolNameCore = symbol.DisplayNameCore @@ -942,6 +922,65 @@ module Commands = return (symbol, dict) } + /// * `includeDeclarations`: + /// if `false` only returns usage locations and excludes declarations + /// * Note: if `true` you can still separate usages and declarations from each other + /// with `Symbol.partitionInfoDeclarationsAndUsages` + /// * `includeBackticks`: + /// if `true` returns ranges including existing backticks, otherwise without: + /// `let _ = ``my value`` + 42` + /// * `true`: ` ``my value`` ` + /// * `false`: `my value` + /// * `errorOnFailureToFixRange`: + /// Ranges returned by FCS don't just span the actual identifier, but include Namespace, Module, Type: `System.String.IsNullOrEmpty` + /// These ranges gets adjusted to include just the concrete identifier (`IsNullOrEmpty`) + /// * If `false` and range cannot be adjust, the original range gets used. + /// * When results are more important than always exact range + /// -> for "Find All References" + /// * If `true`: Instead of using the source range, this function instead returns an Error + /// * When exact ranges are required + /// -> for "Rename" + let symbolUseWorkspace + (getDeclarationLocation: FSharpSymbolUse * IFSACSourceText -> Async) + (findReferencesForSymbolInFile: (string * FSharpProjectOptions * FSharpSymbol) -> Async) + (tryGetFileSource: string -> Async>) + (tryGetProjectOptionsForFsproj: string -> Async) + (getAllProjectOptions: unit -> Async) + (includeDeclarations: bool) + (includeBackticks: bool) + (errorOnFailureToFixRange: bool) + pos + lineStr + (text: IFSACSourceText) + (tyRes: ParseAndCheckResults) + : Async, Range[]>), string>> = + asyncResult { + let multipleSymbols = tyRes.TryGetSymbolUses pos lineStr + let result = Dictionary, Range[]>() + + for symbolUse in multipleSymbols do + let! symbolResult = + symbolUseWorkspaceAux + getDeclarationLocation + findReferencesForSymbolInFile + tryGetFileSource + tryGetProjectOptionsForFsproj + getAllProjectOptions + includeDeclarations + includeBackticks + errorOnFailureToFixRange + text + tyRes + symbolUse + + for KeyValue(k, v) in snd symbolResult do + if result.ContainsKey k then + result.[k] <- [| yield! result.[k]; yield! v |] + else + result.Add(k, v) + + return result + } /// Puts `newName` into backticks if necessary. /// @@ -2009,7 +2048,7 @@ type Commands | SynValData(memberFlags = Some({ MemberKind = SynMemberKind.PropertyGet })) | SynValData(memberFlags = Some({ MemberKind = SynMemberKind.PropertySet })) | SynValData(memberFlags = Some({ MemberKind = SynMemberKind.PropertyGetSet })) -> None - | _ -> Some() + | _ -> Some false | _ -> defaultTraverse synBinding member _.VisitComponentInfo(_, synComponentInfo) = @@ -2017,7 +2056,7 @@ type Commands | SynComponentInfo(longId = longId; xmlDoc = xmlDoc) when longIdentContainsPos longId pos && xmlDoc.IsEmpty -> - Some() + Some false | _ -> None member _.VisitRecordDefn(_, fields, _) = @@ -2026,7 +2065,7 @@ type Commands | SynField(xmlDoc = xmlDoc; idOpt = Some ident) when rangeContainsPos ident.idRange pos && xmlDoc.IsEmpty -> - Some() + Some false | _ -> None fields |> List.tryPick isInLine @@ -2037,7 +2076,7 @@ type Commands | SynUnionCase(xmlDoc = xmlDoc; ident = (SynIdent(ident = ident))) when rangeContainsPos ident.idRange pos && xmlDoc.IsEmpty -> - Some() + Some false | _ -> None cases |> List.tryPick isInLine @@ -2048,7 +2087,7 @@ type Commands | SynEnumCase(xmlDoc = xmlDoc; ident = (SynIdent(ident = ident))) when rangeContainsPos ident.idRange pos && xmlDoc.IsEmpty -> - Some() + Some false | _ -> None cases |> List.tryPick isInLine @@ -2059,7 +2098,7 @@ type Commands | SynBinding(xmlDoc = xmlDoc) as s when rangeContainsPos s.RangeOfBindingWithoutRhs pos && xmlDoc.IsEmpty -> - Some() + Some false | _ -> defaultTraverse b bindings |> List.tryPick isInLine @@ -2078,7 +2117,7 @@ type Commands | SynModuleOrNamespace(longId = longId; xmlDoc = xmlDoc) when longIdentContainsPos longId pos && xmlDoc.IsEmpty -> - Some() + Some false | SynModuleOrNamespace(decls = decls) -> let rec findNested decls = @@ -2090,7 +2129,7 @@ type Commands | SynComponentInfo(longId = longId; xmlDoc = xmlDoc) when longIdentContainsPos longId pos && xmlDoc.IsEmpty -> - Some() + Some false | _ -> findNested decls | SynModuleDecl.Types(typeDefns = typeDefns) -> typeDefns @@ -2103,19 +2142,19 @@ type Commands | SynMemberDefn.AutoProperty(ident = ident; xmlDoc = xmlDoc) when rangeContainsPos ident.idRange pos && xmlDoc.IsEmpty -> - Some() + Some true | SynMemberDefn.GetSetMember( - memberDefnForGet = Some(SynBinding( + memberDefnForSet = Some(SynBinding( xmlDoc = xmlDoc; headPat = SynPat.LongIdent(longDotId = longDotId)))) when rangeContainsPos longDotId.Range pos && xmlDoc.IsEmpty -> - Some() + Some false | SynMemberDefn.GetSetMember( - memberDefnForSet = Some(SynBinding( + memberDefnForGet = Some(SynBinding( xmlDoc = xmlDoc; headPat = SynPat.LongIdent(longDotId = longDotId)))) when rangeContainsPos longDotId.Range pos && xmlDoc.IsEmpty -> - Some() + Some false | _ -> None) | _ -> None) | _ -> None) @@ -2125,7 +2164,7 @@ type Commands let isAstElemWithEmptyPreXmlDoc input pos = match isLowerAstElemWithEmptyPreXmlDoc input pos with - | Some xml -> Some xml + | Some isAutoProperty -> Some isAutoProperty | _ -> isModuleOrNamespaceOrAutoPropertyWithEmptyPreXmlDoc input pos let trimmed = lineStr.TrimStart(' ') @@ -2134,7 +2173,7 @@ type Commands match isAstElemWithEmptyPreXmlDoc tyRes.GetAST triggerPosition with | None -> return None - | Some() -> + | Some(isAutoProperty) -> let signatureData = Commands.SignatureData tyRes triggerPosition lineStr |> Result.ofCoreResponse @@ -2157,6 +2196,7 @@ type Commands | Ok(Some(_, memberParameters, genericParameters)) -> match memberParameters with | [] -> () + | _ when isAutoProperty -> () // no parameter section for auto properties | parameters -> yield! parameters @@ -2256,7 +2296,7 @@ type Commands // safety check: rename valid? let! _ = x.RenameSymbolRange(pos, tyRes, lineStr, text) - let! (_, usages) = x.SymbolUseWorkspace(pos, lineStr, text, tyRes, true, true, true) + let! usages = x.SymbolUseWorkspace(pos, lineStr, text, tyRes, true, true, true) return usages } diff --git a/src/FsAutoComplete.Core/CompilerServiceInterface.fs b/src/FsAutoComplete.Core/CompilerServiceInterface.fs index a167bbc14..e4540034d 100644 --- a/src/FsAutoComplete.Core/CompilerServiceInterface.fs +++ b/src/FsAutoComplete.Core/CompilerServiceInterface.fs @@ -17,20 +17,21 @@ open FsToolkit.ErrorHandling type Version = int -type FSharpCompilerServiceChecker(hasAnalyzers, typecheckCacheSize) = +type FSharpCompilerServiceChecker(hasAnalyzers, typecheckCacheSize, parallelReferenceResolution) = let checker = FSharpChecker.Create( projectCacheSize = 200, - keepAllBackgroundResolutions = true, keepAssemblyContents = hasAnalyzers, + keepAllBackgroundResolutions = true, suggestNamesForErrors = true, - enablePartialTypeChecking = not hasAnalyzers, + keepAllBackgroundSymbolUses = true, enableBackgroundItemKeyStoreAndSemanticClassification = true, - keepAllBackgroundSymbolUses = true + enablePartialTypeChecking = not hasAnalyzers, + parallelReferenceResolution = parallelReferenceResolution, + captureIdentifiersWhenParsing = true, + useSyntaxTreeCache = true ) - - let entityCache = EntityCache() // This is used to hold previous check results for autocompletion. diff --git a/src/FsAutoComplete.Core/CompilerServiceInterface.fsi b/src/FsAutoComplete.Core/CompilerServiceInterface.fsi index 93f383d4d..4d1bbdb58 100644 --- a/src/FsAutoComplete.Core/CompilerServiceInterface.fsi +++ b/src/FsAutoComplete.Core/CompilerServiceInterface.fsi @@ -16,7 +16,9 @@ open FsToolkit.ErrorHandling type Version = int type FSharpCompilerServiceChecker = - new: hasAnalyzers: bool * typecheckCacheSize: int64 -> FSharpCompilerServiceChecker + new: + hasAnalyzers: bool * typecheckCacheSize: int64 * parallelReferenceResolution: bool -> FSharpCompilerServiceChecker + member DisableInMemoryProjectReferences: bool with get, set static member GetDependingProjects: diff --git a/src/FsAutoComplete.Core/InlayHints.fs b/src/FsAutoComplete.Core/InlayHints.fs index 724b4d9c8..215f5101f 100644 --- a/src/FsAutoComplete.Core/InlayHints.fs +++ b/src/FsAutoComplete.Core/InlayHints.fs @@ -31,7 +31,7 @@ and private defaultTraversePat visitor origPath pat = | SynPat.As(p1, p2, _) | SynPat.Or(p1, p2, _, _) -> [ p1; p2 ] |> List.tryPick (traversePat visitor path) | SynPat.Ands(ps, _) - | SynPat.Tuple(_, ps, _) + | SynPat.Tuple(elementPats = ps) | SynPat.ArrayOrList(_, ps, _) -> ps |> List.tryPick (traversePat visitor path) | SynPat.Attrib(p, _, _) -> traversePat visitor path p | SynPat.LongIdent(argPats = args) -> diff --git a/src/FsAutoComplete.Core/Lexer.fs b/src/FsAutoComplete.Core/Lexer.fs index 387e63972..cc7d503b3 100644 --- a/src/FsAutoComplete.Core/Lexer.fs +++ b/src/FsAutoComplete.Core/Lexer.fs @@ -41,14 +41,35 @@ type private DraftToken = module Lexer = let logger = LogProvider.getLoggerByName "Lexer" + [] + let (|Define|_|) (a: string) = + if a.StartsWith "--defin:" then + ValueSome(a.[9..]) + else + ValueNone + + [] + let (|LangVersion|_|) (a: string) = + if a.StartsWith "--langversion:" then + ValueSome(a.[14..]) + else + ValueNone + /// Return all tokens of current line let tokenizeLine (args: string[]) lineStr = - let defines = - args - |> Seq.choose (fun s -> if s.StartsWith "--define:" then Some s.[9..] else None) - |> Seq.toList + let defines, langVersion = + ((ResizeArray(), None), args) + ||> Array.fold (fun (defines, langVersion) arg -> + match arg with + | Define d -> + defines.Add(d) + defines, langVersion + | LangVersion v -> defines, Some(v) + | _ -> defines, langVersion) + + let sourceTokenizer = + FSharpSourceTokenizer(Seq.toList defines, Some "/tmp.fsx", langVersion) - let sourceTokenizer = FSharpSourceTokenizer(defines, Some "/tmp.fsx") let lineTokenizer = sourceTokenizer.CreateLineTokenizer lineStr let rec loop lexState acc = diff --git a/src/FsAutoComplete.Core/ParseAndCheckResults.fs b/src/FsAutoComplete.Core/ParseAndCheckResults.fs index ca3c13fa2..4c820231d 100644 --- a/src/FsAutoComplete.Core/ParseAndCheckResults.fs +++ b/src/FsAutoComplete.Core/ParseAndCheckResults.fs @@ -500,6 +500,13 @@ type ParseAndCheckResults let identIsland = Array.toList identIsland checkResults.GetSymbolUseAtLocation(pos.Line, colu, lineStr, identIsland) + member __.TryGetSymbolUses (pos: Position) (lineStr: LineStr) : FSharpSymbolUse list = + match Lexer.findLongIdents (pos.Column, lineStr) with + | None -> [] + | Some(colu, identIsland) -> + let identIsland = Array.toList identIsland + checkResults.GetSymbolUsesAtLocation(pos.Line, colu, lineStr, identIsland) + member x.TryGetSymbolUseAndUsages (pos: Position) (lineStr: LineStr) = let symboluse = x.TryGetSymbolUse pos lineStr diff --git a/src/FsAutoComplete.Core/ParseAndCheckResults.fsi b/src/FsAutoComplete.Core/ParseAndCheckResults.fsi index 1db08f7ab..73ae4f0dc 100644 --- a/src/FsAutoComplete.Core/ParseAndCheckResults.fsi +++ b/src/FsAutoComplete.Core/ParseAndCheckResults.fsi @@ -67,6 +67,8 @@ type ParseAndCheckResults = member TryGetSymbolUse: pos: Position -> lineStr: LineStr -> FSharpSymbolUse option + member TryGetSymbolUses: pos: Position -> lineStr: LineStr -> FSharpSymbolUse list + member TryGetSymbolUseAndUsages: pos: Position -> lineStr: LineStr -> Result<(FSharpSymbolUse * FSharpSymbolUse array), string> diff --git a/src/FsAutoComplete.Core/State.fs b/src/FsAutoComplete.Core/State.fs index cae2c9fdd..c45581d2a 100644 --- a/src/FsAutoComplete.Core/State.fs +++ b/src/FsAutoComplete.Core/State.fs @@ -28,10 +28,9 @@ module ProjInfoExtensions = ) if rCase.Name = "PEReference" then - let path: string = fields[0] :?> _ - let getStamp: unit -> DateTime = fields[1] :?> _ - let reader = fields[2] - Some(path, getStamp, reader) + let getStamp: unit -> DateTime = fields[0] :?> _ + let reader = fields[1] + Some(getStamp, reader) else None diff --git a/src/FsAutoComplete.Core/UnionPatternMatchCaseGenerator.fs b/src/FsAutoComplete.Core/UnionPatternMatchCaseGenerator.fs index 8fb51643e..84ee01ce2 100644 --- a/src/FsAutoComplete.Core/UnionPatternMatchCaseGenerator.fs +++ b/src/FsAutoComplete.Core/UnionPatternMatchCaseGenerator.fs @@ -311,7 +311,7 @@ let getWrittenCases (patMatchExpr: PatternMatchExpr) = | SynPat.ListCons _ | SynPat.FromParseError(_, _) -> false - | SynPat.Tuple(_, innerPatList, _) -> List.forall checkPattern innerPatList + | SynPat.Tuple(elementPats = innerPatList) -> List.forall checkPattern innerPatList | SynPat.Record(recordInnerPatList, _) -> recordInnerPatList diff --git a/src/FsAutoComplete.Core/UntypedAstUtils.fs b/src/FsAutoComplete.Core/UntypedAstUtils.fs index 6d495c4ef..c5801ed2b 100644 --- a/src/FsAutoComplete.Core/UntypedAstUtils.fs +++ b/src/FsAutoComplete.Core/UntypedAstUtils.fs @@ -50,8 +50,7 @@ let (|AllAttrs|) (attrs: SynAttributes) = let (|AllSimplePats|) (pats: SynSimplePats) = let rec loop acc pat = match pat with - | SynSimplePats.SimplePats(pats, _) -> acc @ pats - | SynSimplePats.Typed(pats, _, _) -> loop acc pats + | SynSimplePats.SimplePats(pats = pats) -> acc @ pats loop [] pats @@ -122,7 +121,7 @@ let internal getRangesAtPosition input (r: Position) : Range list = and walkPat = function - | SynPat.Tuple(_, pats, r) + | SynPat.Tuple(elementPats = pats; range = r) | SynPat.ArrayOrList(_, pats, r) | SynPat.Ands(pats, r) -> addIfInside r @@ -243,6 +242,7 @@ let internal getRangesAtPosition input (r: Position) : Range list = addIfInside r walkType lhs walkType rhs + | SynType.FromParseError(r) -> addIfInside r and walkClause (SynMatchClause(pat, e1, e2, r, _, _)) = addIfInside r @@ -252,13 +252,9 @@ let internal getRangesAtPosition input (r: Position) : Range list = and walkSimplePats = function - | SynSimplePats.SimplePats(pats, r) -> + | SynSimplePats.SimplePats(pats = pats; range = r) -> addIfInside r List.iter walkSimplePat pats - | SynSimplePats.Typed(pats, ty, r) -> - addIfInside r - walkSimplePats pats - walkType ty and walkInterpolatedStringPart = function diff --git a/src/FsAutoComplete/CodeFixes/AddMissingXmlDocumentation.fs b/src/FsAutoComplete/CodeFixes/AddMissingXmlDocumentation.fs index d559f19ec..7e5c38fa3 100644 --- a/src/FsAutoComplete/CodeFixes/AddMissingXmlDocumentation.fs +++ b/src/FsAutoComplete/CodeFixes/AddMissingXmlDocumentation.fs @@ -14,13 +14,13 @@ let title = "Add missing XML documentation" let private tryGetExistingXmlDoc (pos: FSharp.Compiler.Text.Position) (xmlDoc: PreXmlDoc) = let tryGetSummaryIfContainsPos (xd: PreXmlDoc) = - let d = xd.ToXmlDoc(false, None) + if rangeContainsPos xd.Range pos then + let d = xd.ToXmlDoc(false, None) - if rangeContainsPos d.Range pos then if Array.isEmpty d.UnprocessedLines then None elif d.UnprocessedLines |> Array.exists (fun s -> s.Contains("")) then - Some(d.UnprocessedLines, d.Range) + Some(d.UnprocessedLines, xd.Range) else let lines = match d.UnprocessedLines with @@ -28,7 +28,7 @@ let private tryGetExistingXmlDoc (pos: FSharp.Compiler.Text.Position) (xmlDoc: P | [| c |] -> [| $" %s{c.Trim()}" |] | cs -> [| yield " "; yield! cs; yield " " |] - Some(lines, d.Range) + Some(lines, xd.Range) else None @@ -50,7 +50,7 @@ let private tryGetCommentsAndSymbolPos input pos = | SynPat.LongIdent(longDotId = longDotId) -> longDotId.Range.End | _ -> s.RangeOfHeadPattern.Start // for use statements - Some(docLines, docRange, symbolRange) + Some(docLines, docRange, symbolRange, false) | None -> defaultTraverse synBinding SyntaxTraversal.Traverse( @@ -89,7 +89,7 @@ let private tryGetCommentsAndSymbolPos input pos = let docAndDocRange = tryGetExistingXmlDoc pos xmlDoc match docAndDocRange with - | Some(docLines, docRange) -> Some(docLines, docRange, ident.idRange.End) + | Some(docLines, docRange) -> Some(docLines, docRange, ident.idRange.End, true) | _ -> None | _ -> None) | _ -> None) @@ -115,7 +115,7 @@ let fix (getParseResultsForFile: GetParseResultsForFile) : CodeFix = let commentsAndPos = tryGetCommentsAndSymbolPos parseAndCheck.GetAST fcsPos match commentsAndPos with - | Some(docLines, docRange, symbolPos) -> + | Some(docLines, docRange, symbolPos, isAutoProperty) -> let lineStrOfSymbol = _sourceText.GetLine symbolPos |> Option.defaultValue "" let signatureData = parseAndCheck.TryGetSignatureData symbolPos lineStrOfSymbol @@ -133,16 +133,21 @@ let fix (getParseResultsForFile: GetParseResultsForFile) : CodeFix = |> List.tryFindIndexBack (fun s -> s.Contains("") || s.Contains("")) let missingParams = - match memberParameters with - | [] -> [] - | parameters -> - parameters - |> List.concat - |> List.filter (fun (parameter, _) -> - docLines - |> List.exists (fun c -> c.Contains($"")) - |> not) - |> List.mapi (fun _index parameter -> parameterSection parameter) + if isAutoProperty then + // An auto property has a setter symbol which takes a parameter. + // As the user didn't write this parameter, a missing parameter should not be returned. + [] + else + match memberParameters with + | [] -> [] + | parameters -> + parameters + |> List.concat + |> List.filter (fun (parameter, _) -> + docLines + |> List.exists (fun c -> c.Contains($"")) + |> not) + |> List.mapi (fun _index parameter -> parameterSection parameter) match indexForParams with | None -> List.append docLines missingParams diff --git a/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fs b/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fs index 0dd625a12..a9b6bd659 100644 --- a/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fs +++ b/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fs @@ -19,8 +19,7 @@ type SymbolUseWorkspace = -> LineStr -> IFSACSourceText -> ParseAndCheckResults - -> Async, FSharp.Compiler.Text.range array>, string>> + -> Async, FSharp.Compiler.Text.range array>, string>> type private Placement = | Before @@ -204,7 +203,7 @@ let fix (getParseResultsForFile: GetParseResultsForFile) (symbolUseWorkspace: Sy match rangesAndPlacement with | Some(editRange, declRange, placement) -> - let! (_, uses) = symbolUseWorkspace false true true fcsPos lineStr sourceText parseAndCheck + let! uses = symbolUseWorkspace false true true fcsPos lineStr sourceText parseAndCheck let useRanges = uses.Values |> Array.concat let usedOutsideOfDecl = diff --git a/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fsi b/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fsi index d4780a923..932009bbf 100644 --- a/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fsi +++ b/src/FsAutoComplete/CodeFixes/AddPrivateAccessModifier.fsi @@ -19,8 +19,7 @@ type SymbolUseWorkspace = -> LineStr -> IFSACSourceText -> ParseAndCheckResults - -> Async, FSharp.Compiler.Text.range array>, string>> + -> Async, FSharp.Compiler.Text.range array>, string>> val fix: getParseResultsForFile: GetParseResultsForFile -> diff --git a/src/FsAutoComplete/CodeFixes/ConvertTripleSlashCommentToXmlTaggedDoc.fs b/src/FsAutoComplete/CodeFixes/ConvertTripleSlashCommentToXmlTaggedDoc.fs index 31076b723..74aeaa0ce 100644 --- a/src/FsAutoComplete/CodeFixes/ConvertTripleSlashCommentToXmlTaggedDoc.fs +++ b/src/FsAutoComplete/CodeFixes/ConvertTripleSlashCommentToXmlTaggedDoc.fs @@ -14,9 +14,9 @@ let title = "Convert '///' comment to XML-tagged doc comment" let private containsPosAndNotEmptyAndNotElaborated (pos: FSharp.Compiler.Text.Position) (xmlDoc: PreXmlDoc) = let containsPosAndNoSummaryPresent (xd: PreXmlDoc) = - let d = xd.ToXmlDoc(false, None) + if rangeContainsPos xd.Range pos then + let d = xd.ToXmlDoc(false, None) - if rangeContainsPos d.Range pos then let summaryPresent = d.UnprocessedLines |> Array.exists (fun s -> s.Contains("")) diff --git a/src/FsAutoComplete/CodeFixes/RenameUnusedValue.fs b/src/FsAutoComplete/CodeFixes/RenameUnusedValue.fs index e8b5e74af..2d4539f7b 100644 --- a/src/FsAutoComplete/CodeFixes/RenameUnusedValue.fs +++ b/src/FsAutoComplete/CodeFixes/RenameUnusedValue.fs @@ -18,22 +18,19 @@ let titlePrefix = "Prefix with _" /// But current FCS version doesn't include range for `SynAccess` /// -> no (easy) way to get range with accessibility /// -> instead of range to replace, just if there's accessibility -let private variableHasAccessibility (ast: ParsedInput) (pos: Position) = +let private accessibilityRange (ast: ParsedInput) (pos: Position) = SyntaxTraversal.Traverse( pos, ast, { new SyntaxVisitorBase<_>() with member _.VisitPat(_, defaultTraverse, pat) = match pat with - | SynPat.Named(accessibility = Some _; range = range) when Range.rangeContainsPos range pos -> - // `SynAccess` in FCS version currently used in FSAC doesn't contain its range - // -> no easy way to get range with accessibility - // -> instead of returning range with accessibility, just info if there's accessibility - // TODO: return range with accessibility once available (https://github.com/dotnet/fsharp/pull/13304) - Some true + | SynPat.Named(accessibility = Some(SynAccess.Private(range = accessRange)); range = range) when + Range.rangeContainsPos range pos + -> + Some(accessRange.WithEnd(accessRange.End.WithColumn(accessRange.End.Column + 1))) // add an additional column to remove the 'space' between private and identifier | _ -> defaultTraverse pat } ) - |> Option.defaultValue false /// a codefix that suggests prepending a _ to unused values let fix (getParseResultsForFile: GetParseResultsForFile) = @@ -43,14 +40,21 @@ let fix (getParseResultsForFile: GetParseResultsForFile) = let startPos = protocolPosToPos codeActionParams.Range.Start let! (tyRes, line, lines) = getParseResultsForFile fileName startPos + let underscore range : Ionide.LanguageServerProtocol.Types.TextEdit = { Range = range; NewText = "_" } + let mkFix title range = { SourceDiagnostic = Some diagnostic File = codeActionParams.TextDocument Title = title - Edits = [| { Range = range; NewText = "_" } |] + Edits = [| underscore range |] Kind = FixKind.Refactor } - let mkReplaceFix = mkFix titleReplace + let mkReplaceFix identRange accessRange = + match accessRange with + | None -> mkFix titleReplace identRange + | Some accessRange -> + { mkFix titleReplace identRange with + Edits = [| underscore identRange; { Range = accessRange; NewText = "" } |] } let tryMkPrefixFix range = match lines.GetText(protocolRangeToRange (UMX.untag fileName) range) with @@ -60,11 +64,8 @@ let fix (getParseResultsForFile: GetParseResultsForFile) = | _ -> None let tryMkValueReplaceFix (range: Ionide.LanguageServerProtocol.Types.Range) = - // // `let private foo = ...` -> `private` must be removed (`let private _ = ...` is not valid) - if variableHasAccessibility tyRes.GetAST (protocolPosToPos range.Start) then - None - else - mkReplaceFix range |> Some + mkReplaceFix range (accessibilityRange tyRes.GetAST startPos |> Option.map fcsRangeToLsp) + |> Some // CodeFixes: // * Replace with _ @@ -79,7 +80,7 @@ let fix (getParseResultsForFile: GetParseResultsForFile) = match symbolUse.Symbol with | :? FSharpMemberOrFunctionOrValue as mfv -> if mfv.IsMemberThisValue then - return [ mkReplaceFix diagnostic.Range ] + return [ mkReplaceFix diagnostic.Range None ] elif mfv.IsValue then let symbolText = lines.GetText symbolUse.Range diff --git a/src/FsAutoComplete/LspHelpers.fs b/src/FsAutoComplete/LspHelpers.fs index 91d60d5a4..e78015382 100644 --- a/src/FsAutoComplete/LspHelpers.fs +++ b/src/FsAutoComplete/LspHelpers.fs @@ -630,6 +630,7 @@ type FSACDto = { /// The for typecheck cache. CachedTypeCheckCount: int64 option + ParallelReferenceResolution: bool option } type FSharpConfigDto = @@ -728,16 +729,23 @@ type FSACConfig = { /// The for typecheck cache. CachedTypeCheckCount: int64 + /// Whether to use parallel reference resolution in the compiler. See the docs for details. + ParallelReferenceResolution: bool } - static member Default = { CachedTypeCheckCount = 200L } + static member Default = + { CachedTypeCheckCount = 200L + ParallelReferenceResolution = true } static member FromDto(dto: FSACDto) = let defaultConfig = FSACConfig.Default - { CachedTypeCheckCount = defaultArg dto.CachedTypeCheckCount defaultConfig.CachedTypeCheckCount } + + { CachedTypeCheckCount = defaultArg dto.CachedTypeCheckCount defaultConfig.CachedTypeCheckCount + ParallelReferenceResolution = defaultArg dto.ParallelReferenceResolution defaultConfig.ParallelReferenceResolution } member this.AddDto(dto: FSACDto) = - { CachedTypeCheckCount = defaultArg dto.CachedTypeCheckCount this.CachedTypeCheckCount } + { CachedTypeCheckCount = defaultArg dto.CachedTypeCheckCount this.CachedTypeCheckCount + ParallelReferenceResolution = defaultArg dto.ParallelReferenceResolution this.ParallelReferenceResolution } type DebugConfig = { DontCheckRelatedFiles: bool diff --git a/src/FsAutoComplete/LspHelpers.fsi b/src/FsAutoComplete/LspHelpers.fsi index bacd85c4f..5651e61b1 100644 --- a/src/FsAutoComplete/LspHelpers.fsi +++ b/src/FsAutoComplete/LspHelpers.fsi @@ -258,6 +258,7 @@ type FSACDto = { /// The for typecheck cache. CachedTypeCheckCount: int64 option + ParallelReferenceResolution: bool option } type FSharpConfigDto = @@ -338,6 +339,8 @@ type FSACConfig = { /// The for typecheck cache. CachedTypeCheckCount: int64 + /// Whether to use parallel reference resolution in the compiler. See the docs for details. + ParallelReferenceResolution: bool } static member Default: FSACConfig diff --git a/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs b/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs index 544dd27f9..b92ac2875 100644 --- a/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs +++ b/src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs @@ -98,7 +98,7 @@ type AdaptiveFSharpLspServer let checker = config - |> AVal.map (fun c -> c.EnableAnalyzers, c.Fsac.CachedTypeCheckCount) + |> AVal.map (fun c -> c.EnableAnalyzers, c.Fsac.CachedTypeCheckCount, c.Fsac.ParallelReferenceResolution) |> AVal.map (FSharpCompilerServiceChecker) /// The reality is a file can be in multiple projects @@ -1642,6 +1642,48 @@ type AdaptiveFSharpLspServer text tyRes + let symbolUseWorkspace2 + (includeDeclarations: bool) + (includeBackticks: bool) + (errorOnFailureToFixRange: bool) + pos + lineStr + text + tyRes + = + let findReferencesForSymbolInFile (file: string, project, symbol) = + async { + let checker = checker |> AVal.force + + if File.Exists(UMX.untag file) then + // `FSharpChecker.FindBackgroundReferencesInFile` only works with existing files + return! checker.FindReferencesForSymbolInFile(UMX.untag file, project, symbol) + else + // untitled script files + match! forceGetTypeCheckResultsStale file with + | Error _ -> return Seq.empty + | Ok tyRes -> + let! ct = Async.CancellationToken + let usages = tyRes.GetCheckResults.GetUsesOfSymbolInFile(symbol, ct) + return usages |> Seq.map (fun u -> u.Range) + } + + let tryGetProjectOptionsForFsproj (file: string) = + forceGetFSharpProjectOptions file |> Async.map Option.ofResult + + Commands.symbolUseWorkspace + getDeclarationLocation + findReferencesForSymbolInFile + forceFindSourceText + tryGetProjectOptionsForFsproj + (getAllFSharpProjectOptions >> Async.map Array.toSeq) + includeDeclarations + includeBackticks + errorOnFailureToFixRange + pos + lineStr + text + tyRes let codefixes = @@ -1780,7 +1822,7 @@ type AdaptiveFSharpLspServer RemoveRedundantAttributeSuffix.fix tryGetParseResultsForFile Run.ifEnabled (fun _ -> config.AddPrivateAccessModifier) - (AddPrivateAccessModifier.fix tryGetParseResultsForFile symbolUseWorkspace) + (AddPrivateAccessModifier.fix tryGetParseResultsForFile symbolUseWorkspace2) UseTripleQuotedInterpolation.fix tryGetParseResultsForFile getRangeText RenameParamToMatchSignature.fix tryGetParseResultsForFile RemovePatternArgument.fix tryGetParseResultsForFile @@ -2889,7 +2931,7 @@ type AdaptiveFSharpLspServer Commands.renameSymbolRange getDeclarationLocation false pos lineStr volatileFile.Source tyRes |> AsyncResult.mapError (fun msg -> JsonRpc.Error.Create(JsonRpc.ErrorCodes.invalidParams, msg)) - let! (_, ranges) = + let! ranges = symbolUseWorkspace true true true pos lineStr volatileFile.Source tyRes |> AsyncResult.mapError (fun msg -> JsonRpc.Error.Create(JsonRpc.ErrorCodes.invalidParams, msg)) @@ -3010,7 +3052,7 @@ type AdaptiveFSharpLspServer let! lineStr = tryGetLineStr pos volatileFile.Source |> Result.ofStringErr and! tyRes = forceGetTypeCheckResults filePath |> AsyncResult.ofStringErr - let! (_, usages) = + let! usages = symbolUseWorkspace true true false pos lineStr volatileFile.Source tyRes |> AsyncResult.mapError (JsonRpc.Error.InternalErrorMessage) @@ -3548,7 +3590,7 @@ type AdaptiveFSharpLspServer Arguments = None } } ) - | Ok(_, uses) -> + | Ok uses -> let allUses = uses.Values |> Array.concat let cmd = diff --git a/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs b/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs index 9994b6b61..b11db9eee 100644 --- a/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs +++ b/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs @@ -47,7 +47,7 @@ type FSharpLspServer(state: State, lspClient: FSharpLspClient, sourceTextFactory let mutable rootPath: string option = None let mutable commands = - new Commands(FSharpCompilerServiceChecker(false, 200L), state, false, rootPath, sourceTextFactory) + new Commands(FSharpCompilerServiceChecker(false, 200L, false), state, false, rootPath, sourceTextFactory) let mutable commandDisposables = ResizeArray() let mutable clientCapabilities: ClientCapabilities option = None @@ -486,7 +486,11 @@ type FSharpLspServer(state: State, lspClient: FSharpLspClient, sourceTextFactory let newCommands = new Commands( - FSharpCompilerServiceChecker(hasAnalyzersNow, config.Fsac.CachedTypeCheckCount), + FSharpCompilerServiceChecker( + hasAnalyzersNow, + config.Fsac.CachedTypeCheckCount, + config.Fsac.ParallelReferenceResolution + ), state, hasAnalyzersNow, rootPath, @@ -1689,7 +1693,7 @@ type FSharpLspServer(state: State, lspClient: FSharpLspClient, sourceTextFactory p |> x.positionHandler (fun p pos tyRes lineStr lines -> asyncResult { - let! (_, usages) = + let! usages = commands.SymbolUseWorkspace(pos, lineStr, lines, tyRes, true, true, false) |> AsyncResult.mapError (JsonRpc.Error.InternalErrorMessage) @@ -2062,7 +2066,7 @@ type FSharpLspServer(state: State, lspClient: FSharpLspClient, sourceTextFactory Arguments = None } } ) - | Ok(_, uses) -> + | Ok uses -> let allUses = uses.Values |> Array.concat let cmd = diff --git a/src/FsAutoComplete/paket.references b/src/FsAutoComplete/paket.references index cec270234..29b7a6a7a 100644 --- a/src/FsAutoComplete/paket.references +++ b/src/FsAutoComplete/paket.references @@ -8,8 +8,8 @@ FSharp.Core FSharp.UMX FsToolkit.ErrorHandling FsToolkit.ErrorHandling.TaskResult -ICSharpCode.Decompiler IcedTasks +ICSharpCode.Decompiler Ionide.KeepAChangelog.Tasks Ionide.LanguageServerProtocol Ionide.ProjInfo.ProjectSystem diff --git a/test/FsAutoComplete.Tests.Lsp/CodeFixTests/Tests.fs b/test/FsAutoComplete.Tests.Lsp/CodeFixTests/Tests.fs index ad355fb9d..9230d36a8 100644 --- a/test/FsAutoComplete.Tests.Lsp/CodeFixTests/Tests.fs +++ b/test/FsAutoComplete.Tests.Lsp/CodeFixTests/Tests.fs @@ -8,10 +8,12 @@ open Ionide.LanguageServerProtocol.Types open FsAutoComplete.CodeFix let private addMissingEqualsToTypeDefinitionTests state = - serverTestList (nameof AddMissingEqualsToTypeDefinition) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle AddMissingEqualsToTypeDefinition.title - testCaseAsync "can add = to record def" <| - CodeFix.check server + serverTestList (nameof AddMissingEqualsToTypeDefinition) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle AddMissingEqualsToTypeDefinition.title + + testCaseAsync "can add = to record def" + <| CodeFix.check + server """ type Person $0{ Name : string; Age : int; City : string } """ @@ -20,8 +22,10 @@ let private addMissingEqualsToTypeDefinitionTests state = """ type Person = { Name : string; Age : int; City : string } """ - testCaseAsync "can add = to union def" <| - CodeFix.check server + + testCaseAsync "can add = to union def" + <| CodeFix.check + server """ type Name $0Name of string """ @@ -29,13 +33,13 @@ let private addMissingEqualsToTypeDefinitionTests state = selectCodeFix """ type Name = Name of string - """ - ]) + """ ]) let private addMissingFunKeywordTests state = - serverTestList (nameof AddMissingFunKeyword) state defaultConfigDto None (fun server -> [ - testCaseAsync "can generate the fun keyword when error 10 is raised" <| - CodeFix.check server + serverTestList (nameof AddMissingFunKeyword) state defaultConfigDto None (fun server -> + [ testCaseAsync "can generate the fun keyword when error 10 is raised" + <| CodeFix.check + server """ let doThing = x $0-> printfn "%s" x """ @@ -43,13 +47,13 @@ let private addMissingFunKeywordTests state = (CodeFix.ofKind "quickfix" >> CodeFix.withTitle AddMissingFunKeyword.title) """ let doThing = fun x -> printfn "%s" x - """ - ]) + """ ]) let private addMissingInstanceMemberTests state = - serverTestList (nameof AddMissingInstanceMember) state defaultConfigDto None (fun server -> [ - testCaseAsync "can add this member prefix" <| - CodeFix.check server + serverTestList (nameof AddMissingInstanceMember) state defaultConfigDto None (fun server -> + [ testCaseAsync "can add this member prefix" + <| CodeFix.check + server """ type C () = member $0Foo() = () @@ -59,14 +63,15 @@ let private addMissingInstanceMemberTests state = """ type C () = member x.Foo() = () - """ - ]) + """ ]) let private addMissingRecKeywordTests state = - serverTestList (nameof AddMissingRecKeyword) state defaultConfigDto None (fun server -> [ - // `rec` in single function is handled in `MakeOuterBindingRecursive` - testCaseAsync "can add rec to mutual recursive function" <| - CodeFix.check server + serverTestList (nameof AddMissingRecKeyword) state defaultConfigDto None (fun server -> + [ + // `rec` in single function is handled in `MakeOuterBindingRecursive` + testCaseAsync "can add rec to mutual recursive function" + <| CodeFix.check + server """ $0let a x = x and b x = x @@ -76,14 +81,16 @@ let private addMissingRecKeywordTests state = """ let rec a x = x and b x = x - """ - ]) + """ ]) let private addNewKeywordToDisposableConstructorInvocationTests state = - serverTestList (nameof AddNewKeywordToDisposableConstructorInvocation) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle AddNewKeywordToDisposableConstructorInvocation.title - testCaseAsync "can add new to Disposable" <| - CodeFix.check server + serverTestList (nameof AddNewKeywordToDisposableConstructorInvocation) state defaultConfigDto None (fun server -> + [ let selectCodeFix = + CodeFix.withTitle AddNewKeywordToDisposableConstructorInvocation.title + + testCaseAsync "can add new to Disposable" + <| CodeFix.check + server """ open System.Threading.Tasks let _ = $0Task(fun _ -> 1) @@ -94,8 +101,10 @@ let private addNewKeywordToDisposableConstructorInvocationTests state = open System.Threading.Tasks let _ = new Task(fun _ -> 1) """ - testCaseAsync "can add new to Disposable with namespace" <| - CodeFix.check server + + testCaseAsync "can add new to Disposable with namespace" + <| CodeFix.check + server """ let _ = System.Threading.Tasks.$0Task(fun _ -> 1) """ @@ -104,20 +113,23 @@ let private addNewKeywordToDisposableConstructorInvocationTests state = """ let _ = new System.Threading.Tasks.Task(fun _ -> 1) """ - testCaseAsync "doesn't trigger for not Disposable" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for not Disposable" + <| CodeFix.checkNotApplicable + server """ let _ = System.$0String('.', 3) """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private addTypeToIndeterminateValueTests state = - serverTestList (nameof AddTypeToIndeterminateValue) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle AddTypeToIndeterminateValue.title - testCaseAsync "can add type annotation to error 72 ('Lookup on object of indeterminate type')" <| - CodeFix.check server + serverTestList (nameof AddTypeToIndeterminateValue) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle AddTypeToIndeterminateValue.title + + testCaseAsync "can add type annotation to error 72 ('Lookup on object of indeterminate type')" + <| CodeFix.check + server """ let data = [ {| Name = "foo"; Value = 42 |} @@ -134,8 +146,11 @@ let private addTypeToIndeterminateValueTests state = ] let res = List.filter (fun (d: {| Name: string; Value: int |}) -> d.Value > 20) data """ - testCaseAsync "can add type annotation to error 3245 ('The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record')" <| - CodeFix.check server + + testCaseAsync + "can add type annotation to error 3245 ('The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record')" + <| CodeFix.check + server """ [1..5] |> List.fold @@ -157,14 +172,15 @@ let private addTypeToIndeterminateValueTests state = | _ -> s ) {| Evens = 0 |} - """ - ]) + """ ]) let private changeDerefBangToValueTests state = - serverTestList (nameof ChangeDerefBangToValue) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ChangeDerefBangToValue.title - testCaseAsync "can replace ! with .Value" <| - CodeFix.check server + serverTestList (nameof ChangeDerefBangToValue) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ChangeDerefBangToValue.title + + testCaseAsync "can replace ! with .Value" + <| CodeFix.check + server """ let rv = ref 5 let v = $0!rv @@ -175,8 +191,10 @@ let private changeDerefBangToValueTests state = let rv = ref 5 let v = rv.Value """ - testCaseAsync "can replace ! with .Value when parens" <| - CodeFix.check server + + testCaseAsync "can replace ! with .Value when parens" + <| CodeFix.check + server """ let rv = ref 5 let v = $0!(rv) @@ -187,8 +205,10 @@ let private changeDerefBangToValueTests state = let rv = ref 5 let v = (rv).Value """ - testCaseAsync "can replace ! with .Value when function in parens" <| - CodeFix.check server + + testCaseAsync "can replace ! with .Value when function in parens" + <| CodeFix.check + server """ let fr a = ref a let v = $0!(fr 5) @@ -199,8 +219,10 @@ let private changeDerefBangToValueTests state = let fr a = ref a let v = (fr 5).Value """ - testCaseAsync "can replace ! with .Value when space between ! and variable" <| - CodeFix.check server + + testCaseAsync "can replace ! with .Value when space between ! and variable" + <| CodeFix.check + server """ let rv = ref 5 let v = $0! rv @@ -211,8 +233,10 @@ let private changeDerefBangToValueTests state = let rv = ref 5 let v = rv.Value """ - testCaseAsync "can replace ! with .Value when when parens and space between ! and variable" <| - CodeFix.check server + + testCaseAsync "can replace ! with .Value when when parens and space between ! and variable" + <| CodeFix.check + server """ let rv = ref 5 let v = $0! (rv) @@ -222,15 +246,19 @@ let private changeDerefBangToValueTests state = """ let rv = ref 5 let v = (rv).Value - """ - ]) + """ ]) let private changeDowncastToUpcastTests state = - serverTestList (nameof ChangeDowncastToUpcast) state defaultConfigDto None (fun server -> [ - let selectOperatorCodeFix = CodeFix.withTitle ChangeDowncastToUpcast.titleUpcastOperator - let selectFunctionCodeFix = CodeFix.withTitle ChangeDowncastToUpcast.titleUpcastFunction - testCaseAsync "can change :?> to :>" <| - CodeFix.check server + serverTestList (nameof ChangeDowncastToUpcast) state defaultConfigDto None (fun server -> + [ let selectOperatorCodeFix = + CodeFix.withTitle ChangeDowncastToUpcast.titleUpcastOperator + + let selectFunctionCodeFix = + CodeFix.withTitle ChangeDowncastToUpcast.titleUpcastFunction + + testCaseAsync "can change :?> to :>" + <| CodeFix.check + server """ type I = interface end type C() = interface I @@ -245,8 +273,10 @@ let private changeDowncastToUpcastTests state = let v: I = C() :> I """ - testCaseAsync "can change downcast to upcast" <| - CodeFix.check server + + testCaseAsync "can change downcast to upcast" + <| CodeFix.check + server """ type I = interface end type C() = interface I @@ -261,14 +291,16 @@ let private changeDowncastToUpcastTests state = let v: I = upcast C() """ - () - ]) + + () ]) let private changeEqualsInFieldTypeToColonTests state = - serverTestList (nameof ChangeEqualsInFieldTypeToColon) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ChangeEqualsInFieldTypeToColon.title - testCaseAsync "can change = to : in single line" <| - CodeFix.check server + serverTestList (nameof ChangeEqualsInFieldTypeToColon) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ChangeEqualsInFieldTypeToColon.title + + testCaseAsync "can change = to : in single line" + <| CodeFix.check + server """ type A = { Name : string; Key $0= int } """ @@ -277,8 +309,10 @@ let private changeEqualsInFieldTypeToColonTests state = """ type A = { Name : string; Key : int } """ - testCaseAsync "can change = to : in multi line" <| - CodeFix.check server + + testCaseAsync "can change = to : in multi line" + <| CodeFix.check + server """ type A = { Name : string @@ -292,32 +326,34 @@ let private changeEqualsInFieldTypeToColonTests state = Name : string Key : int } - """ - ]) + """ ]) let private changePrefixNegationToInfixSubtractionTests state = - serverTestList (nameof ChangePrefixNegationToInfixSubtraction) state defaultConfigDto None (fun server -> [ - testCaseAsync "converts negation to subtraction" <| - CodeFix.check server + serverTestList (nameof ChangePrefixNegationToInfixSubtraction) state defaultConfigDto None (fun server -> + [ testCaseAsync "converts negation to subtraction" + <| CodeFix.check + server """ let getListWithoutFirstAndLastElement list = let l = List.length list list[ 1 .. $0l -1 ] """ (Diagnostics.expectCode "3") - (CodeFix.ofKind "quickfix" >> CodeFix.withTitle ChangePrefixNegationToInfixSubtraction.title) + (CodeFix.ofKind "quickfix" + >> CodeFix.withTitle ChangePrefixNegationToInfixSubtraction.title) """ let getListWithoutFirstAndLastElement list = let l = List.length list list[ 1 .. l - 1 ] - """ - ]) + """ ]) let private changeRefCellDerefToNotTests state = - serverTestList (nameof ChangeRefCellDerefToNot) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ChangeRefCellDerefToNot.title - testCaseAsync "can change simple deref to not" <| - CodeFix.check server + serverTestList (nameof ChangeRefCellDerefToNot) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ChangeRefCellDerefToNot.title + + testCaseAsync "can change simple deref to not" + <| CodeFix.check + server """ let x = 1 !$0x @@ -328,8 +364,10 @@ let private changeRefCellDerefToNotTests state = let x = 1 not x """ - testCaseAsync "can change simple deref with parens to not" <| - CodeFix.check server + + testCaseAsync "can change simple deref with parens to not" + <| CodeFix.check + server """ let x = 1 !($0x) @@ -340,8 +378,10 @@ let private changeRefCellDerefToNotTests state = let x = 1 not (x) """ - testCaseAsync "can change deref of binary expr to not" <| - CodeFix.check server + + testCaseAsync "can change deref of binary expr to not" + <| CodeFix.check + server """ let x = 1 !($0x = false) @@ -351,13 +391,13 @@ let private changeRefCellDerefToNotTests state = """ let x = 1 not (x = false) - """ - ]) + """ ]) let private changeTypeOfNameToNameOfTests state = - serverTestList (nameof ChangeTypeOfNameToNameOf) state defaultConfigDto None (fun server -> [ - testCaseAsync "can suggest fix" <| - CodeFix.check server + serverTestList (nameof ChangeTypeOfNameToNameOf) state defaultConfigDto None (fun server -> + [ testCaseAsync "can suggest fix" + <| CodeFix.check + server """ let x = $0typeof>.Name """ @@ -365,14 +405,15 @@ let private changeTypeOfNameToNameOfTests state = (CodeFix.ofKind "refactor" >> CodeFix.withTitle ChangeTypeOfNameToNameOf.title) """ let x = nameof(Async) - """ - ]) + """ ]) let private convertBangEqualsToInequalityTests state = - serverTestList (nameof ConvertBangEqualsToInequality) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ConvertBangEqualsToInequality.title - testCaseAsync "can change != to <>" <| - CodeFix.check server + serverTestList (nameof ConvertBangEqualsToInequality) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ConvertBangEqualsToInequality.title + + testCaseAsync "can change != to <>" + <| CodeFix.check + server """ 1 $0!= 2 """ @@ -380,14 +421,15 @@ let private convertBangEqualsToInequalityTests state = selectCodeFix """ 1 <> 2 - """ - ]) + """ ]) let private convertCSharpLambdaToFSharpLambdaTests state = - serverTestList (nameof ConvertCSharpLambdaToFSharpLambda) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ConvertCSharpLambdaToFSharpLambda.title - testCaseAsync "can convert csharp lambda in variable assignment with cursor on input" <| - CodeFix.check server + serverTestList (nameof ConvertCSharpLambdaToFSharpLambda) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ConvertCSharpLambdaToFSharpLambda.title + + testCaseAsync "can convert csharp lambda in variable assignment with cursor on input" + <| CodeFix.check + server """ let x = $0y => 1 + y """ @@ -396,8 +438,10 @@ let private convertCSharpLambdaToFSharpLambdaTests state = """ let x = fun y -> 1 + y """ - testCaseAsync "can convert csharp lambda in variable assignment with cursor on usage" <| - CodeFix.check server + + testCaseAsync "can convert csharp lambda in variable assignment with cursor on usage" + <| CodeFix.check + server """ let x = y => 1 + $0y """ @@ -406,9 +450,10 @@ let private convertCSharpLambdaToFSharpLambdaTests state = """ let x = fun y -> 1 + y """ - //ENHANCEMENT: trigger on `=>` - itestCaseAsync "can convert csharp lambda in variable assignment with cursor on =>" <| - CodeFix.check server + //ENHANCEMENT: trigger on `=>` + itestCaseAsync "can convert csharp lambda in variable assignment with cursor on =>" + <| CodeFix.check + server """ let x = y $0=> 1 + y """ @@ -417,8 +462,10 @@ let private convertCSharpLambdaToFSharpLambdaTests state = """ let x = fun y -> 1 + y """ - testCaseAsync "can convert csharp lambda in lambda with parens with cursor on input" <| - CodeFix.check server + + testCaseAsync "can convert csharp lambda in lambda with parens with cursor on input" + <| CodeFix.check + server """ [1..10] |> List.map ($0x => 1 + x) """ @@ -427,8 +474,10 @@ let private convertCSharpLambdaToFSharpLambdaTests state = """ [1..10] |> List.map (fun x -> 1 + x) """ - testCaseAsync "can convert csharp lambda in lambda with parens with cursor on usage" <| - CodeFix.check server + + testCaseAsync "can convert csharp lambda in lambda with parens with cursor on usage" + <| CodeFix.check + server """ [1..10] |> List.map (x => 1 + $0x) """ @@ -437,8 +486,10 @@ let private convertCSharpLambdaToFSharpLambdaTests state = """ [1..10] |> List.map (fun x -> 1 + x) """ - testCaseAsync "keep multi-line lambda intact - cursor on input" <| - CodeFix.check server + + testCaseAsync "keep multi-line lambda intact - cursor on input" + <| CodeFix.check + server """ let x = $0y => @@ -453,8 +504,10 @@ let private convertCSharpLambdaToFSharpLambdaTests state = let a = 1 + y a """ - testCaseAsync "keep multi-line lambda intact - cursor on usage" <| - CodeFix.check server + + testCaseAsync "keep multi-line lambda intact - cursor on usage" + <| CodeFix.check + server """ let x = y => @@ -468,14 +521,15 @@ let private convertCSharpLambdaToFSharpLambdaTests state = fun y -> let a = 1 + y a - """ - ]) + """ ]) let private convertDoubleEqualsToSingleEqualsTests state = - serverTestList (nameof ConvertDoubleEqualsToSingleEquals) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ConvertDoubleEqualsToSingleEquals.title - testCaseAsync "can replace == with =" <| - CodeFix.check server + serverTestList (nameof ConvertDoubleEqualsToSingleEquals) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ConvertDoubleEqualsToSingleEquals.title + + testCaseAsync "can replace == with =" + <| CodeFix.check + server """ 1 $0== 1 """ @@ -484,21 +538,24 @@ let private convertDoubleEqualsToSingleEqualsTests state = """ 1 = 1 """ - testCaseAsync "doesn't replace existing operator == with =" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't replace existing operator == with =" + <| CodeFix.checkNotApplicable + server """ let (==) a b = a = b 1 $0== 1 """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private convertInvalidRecordToAnonRecordTests state = - serverTestList (nameof ConvertInvalidRecordToAnonRecord) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ConvertInvalidRecordToAnonRecord.title - testCaseAsync "can convert single-line record with single field" <| - CodeFix.check server + serverTestList (nameof ConvertInvalidRecordToAnonRecord) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ConvertInvalidRecordToAnonRecord.title + + testCaseAsync "can convert single-line record with single field" + <| CodeFix.check + server """ let v = { $0Name = "foo" } """ @@ -507,8 +564,10 @@ let private convertInvalidRecordToAnonRecordTests state = """ let v = {| Name = "foo" |} """ - testCaseAsync "can convert single-line record with two fields" <| - CodeFix.check server + + testCaseAsync "can convert single-line record with two fields" + <| CodeFix.check + server """ let v = { $0Name = "foo"; Value = 42 } """ @@ -517,8 +576,10 @@ let private convertInvalidRecordToAnonRecordTests state = """ let v = {| Name = "foo"; Value = 42 |} """ - testCaseAsync "can convert multi-line record with two fields" <| - CodeFix.check server + + testCaseAsync "can convert multi-line record with two fields" + <| CodeFix.check + server """ let v = { $0Name = "foo" @@ -533,28 +594,33 @@ let private convertInvalidRecordToAnonRecordTests state = Value = 42 |} """ - testCaseAsync "doesn't trigger for existing record" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for existing record" + <| CodeFix.checkNotApplicable + server """ type V = { Name: string; Value: int } let v = { $0Name = "foo"; Value = 42 } """ (Diagnostics.acceptAll) selectCodeFix - testCaseAsync "doesn't trigger for anon record" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for anon record" + <| CodeFix.checkNotApplicable + server """ let v = {| $0Name = "foo"; Value = 42 |} """ (Diagnostics.acceptAll) - selectCodeFix - ]) + selectCodeFix ]) let private convertPositionalDUToNamedTests state = - serverTestList (nameof ConvertPositionalDUToNamed) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle ConvertPositionalDUToNamed.title - testCaseAsync "in parenthesized let binding" <| - CodeFix.check server + serverTestList (nameof ConvertPositionalDUToNamed) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle ConvertPositionalDUToNamed.title + + testCaseAsync "in parenthesized let binding" + <| CodeFix.check + server """ type A = A of a: int * b: bool @@ -567,8 +633,10 @@ let private convertPositionalDUToNamedTests state = let (A(a = a; b = b;)) = A(1, true) """ - testCaseAsync "in simple match" <| - CodeFix.check server + + testCaseAsync "in simple match" + <| CodeFix.check + server """ type A = A of a: int * b: bool @@ -585,8 +653,10 @@ let private convertPositionalDUToNamedTests state = | A(_, false) -> () | A(a = a; b = b;) -> () """ - testCaseAsync "in parenthesized match" <| - CodeFix.check server + + testCaseAsync "in parenthesized match" + <| CodeFix.check + server """ type A = A of a: int * b: bool @@ -603,8 +673,10 @@ let private convertPositionalDUToNamedTests state = | (A(_, false)) -> () | (A(a = a; b = b;)) -> () """ - testCaseAsync "when there is one new field on the DU" <| - CodeFix.check server + + testCaseAsync "when there is one new field on the DU" + <| CodeFix.check + server """ type ThirdFieldWasJustAdded = ThirdFieldWasJustAdded of a: int * b: bool * c: char @@ -617,8 +689,10 @@ let private convertPositionalDUToNamedTests state = let (ThirdFieldWasJustAdded(a = a; b = b; c = _;)) = ThirdFieldWasJustAdded(1, true, 'c') """ - testCaseAsync "when there are multiple new fields on the DU" <| - CodeFix.check server + + testCaseAsync "when there are multiple new fields on the DU" + <| CodeFix.check + server """ type U = U of aValue: int * boolean: int * char: char * dec: decimal * element: int let (U($0a, b)) = failwith "..." @@ -629,8 +703,10 @@ let private convertPositionalDUToNamedTests state = type U = U of aValue: int * boolean: int * char: char * dec: decimal * element: int let (U(aValue = a; boolean = b; char = _; dec = _; element = _;)) = failwith "..." """ - testCaseAsync "when the existing pattern isn't formatted well" <| - CodeFix.check server + + testCaseAsync "when the existing pattern isn't formatted well" + <| CodeFix.check + server """ type A = A of a: int * b: bool * c: bool * d: bool let (A($0a,b, c, d)) = A(1, true, false, false) @@ -642,8 +718,9 @@ let private convertPositionalDUToNamedTests state = let (A(a = a;b = b; c = c; d = d;)) = A(1, true, false, false) """ - testCaseAsync "when there are multiple SynLongIdent Pats" <| - CodeFix.check server + testCaseAsync "when there are multiple SynLongIdent Pats" + <| CodeFix.check + server """ type MyDiscUnion = Case1 of field1: int * field2: int @@ -671,8 +748,9 @@ let private convertPositionalDUToNamedTests state = | _ -> () """ - testCaseAsync "when surrounding function takes union parameter" <| - CodeFix.check server + testCaseAsync "when surrounding function takes union parameter" + <| CodeFix.check + server """ type MyDiscUnion = X of field1: int * field2: int @@ -692,11 +770,13 @@ let private convertPositionalDUToNamedTests state = match x with | X(field1 = 32; field2 = 23;) -> () | _ -> () - """ - ]) + """ ]) let private addPrivateAccessModifierTests state = - let config = { defaultConfigDto with AddPrivateAccessModifier = Some true } + let config = + { defaultConfigDto with + AddPrivateAccessModifier = Some true } + serverTestList (nameof AddPrivateAccessModifier) state config None (fun server -> [ let selectCodeFix = CodeFix.withTitle AddPrivateAccessModifier.title @@ -830,7 +910,8 @@ let private addPrivateAccessModifierTests state = Diagnostics.acceptAll selectCodeFix - testCaseAsync "add private is not offered for member with reference outside its declaring class when caret is on thisValue" + testCaseAsync + "add private is not offered for member with reference outside its declaring class when caret is on thisValue" <| CodeFix.checkNotApplicable server """ @@ -941,7 +1022,8 @@ let private addPrivateAccessModifierTests state = Diagnostics.acceptAll selectCodeFix - testCaseAsync "add private is not offered for member with reference outside its declaring DU when caret is on thisValue" + testCaseAsync + "add private is not offered for member with reference outside its declaring DU when caret is on thisValue" <| CodeFix.checkNotApplicable server """ @@ -1017,7 +1099,8 @@ let private addPrivateAccessModifierTests state = Diagnostics.acceptAll selectCodeFix - testCaseAsync "add private is not offered for member with reference outside its declaring Record when caret is on thisValue" + testCaseAsync + "add private is not offered for member with reference outside its declaring Record when caret is on thisValue" <| CodeFix.checkNotApplicable server """ @@ -1131,8 +1214,7 @@ let private addPrivateAccessModifierTests state = let x: M.MyInt = 23 """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private convertTripleSlashCommentToXmlTaggedDocTests state = serverTestList (nameof ConvertTripleSlashCommentToXmlTaggedDoc) state defaultConfigDto None (fun server -> @@ -1634,6 +1716,7 @@ let private generateXmlDocumentationTests state = type MyClass() = let mutable someField = "" /// + /// /// member _.Name with get () = "foo" @@ -1943,36 +2026,38 @@ let private generateRecordStubTests state = let config = { defaultConfigDto with RecordStubGeneration = Some true - RecordStubGenerationBody = Some "failwith \"---\"" - } - serverTestList (nameof GenerateRecordStub) state config None (fun server -> [ - CodeFix.testAllPositions "can generate record stubs for every pos in the record as soon as one field is known" - server - """ + RecordStubGenerationBody = Some "failwith \"---\"" } + + serverTestList (nameof GenerateRecordStub) state config None (fun server -> + [ CodeFix.testAllPositions + "can generate record stubs for every pos in the record as soon as one field is known" + server + """ type R = { a: string; b: int } let a = $0{ $0a = $0"";$0 }$0 """ - (Diagnostics.expectCode "764") - (CodeFix.withTitle GenerateRecordStub.title) - """ + (Diagnostics.expectCode "764") + (CodeFix.withTitle GenerateRecordStub.title) + """ type R = { a: string; b: int } let a = { a = ""; b = failwith "---" } - """ - ]) + """ ]) let private generateUnionCasesTests state = let config = { defaultConfigDto with UnionCaseStubGeneration = Some true - UnionCaseStubGenerationBody = Some "failwith \"---\"" - } - serverTestList (nameof GenerateUnionCases) state config None (fun server -> [ - let selectCodeFix = CodeFix.withTitle GenerateUnionCases.title - testCaseAsync "can generate match cases for a simple DU" <| - CodeFix.check server + UnionCaseStubGenerationBody = Some "failwith \"---\"" } + + serverTestList (nameof GenerateUnionCases) state config None (fun server -> + [ let selectCodeFix = CodeFix.withTitle GenerateUnionCases.title + + testCaseAsync "can generate match cases for a simple DU" + <| CodeFix.check + server """ type Letter = A | B | C @@ -1992,14 +2077,15 @@ let private generateUnionCasesTests state = | A -> () | B -> failwith "---" | C -> failwith "---" - """ - ]) + """ ]) let private makeDeclarationMutableTests state = - serverTestList (nameof MakeDeclarationMutable) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle MakeDeclarationMutable.title - testCaseAsync "can make decl mutable in top level assignment" <| - CodeFix.check server + serverTestList (nameof MakeDeclarationMutable) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle MakeDeclarationMutable.title + + testCaseAsync "can make decl mutable in top level assignment" + <| CodeFix.check + server """ let x = 0 x $0<- 1 @@ -2010,8 +2096,10 @@ let private makeDeclarationMutableTests state = let mutable x = 0 x <- 1 """ - testCaseAsync "can make decl mutable in nested assignment" <| - CodeFix.check server + + testCaseAsync "can make decl mutable in nested assignment" + <| CodeFix.check + server """ let x = 0 let _ = @@ -2026,8 +2114,10 @@ let private makeDeclarationMutableTests state = x <- 1 () """ - testCaseAsync "can make decl mutable in function" <| - CodeFix.check server + + testCaseAsync "can make decl mutable in function" + <| CodeFix.check + server """ let count xs = let counter = 0 @@ -2044,16 +2134,20 @@ let private makeDeclarationMutableTests state = counter <- counter + 1 counter """ - testCaseAsync "doesn't trigger for already mutable variable" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for already mutable variable" + <| CodeFix.checkNotApplicable + server """ let mutable x = 0 x $0<- 1 """ Diagnostics.acceptAll selectCodeFix - testCaseAsync "doesn't trigger for immutable parameter" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for immutable parameter" + <| CodeFix.checkNotApplicable + server """ let f (v: int) = v $0<- 1 @@ -2061,21 +2155,23 @@ let private makeDeclarationMutableTests state = """ Diagnostics.acceptAll selectCodeFix - testCaseAsync "doesn't trigger for immutable member parameter" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for immutable member parameter" + <| CodeFix.checkNotApplicable + server """ type C() = member _.M(v: int) v $0<- 1 """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private makeOuterBindingRecursiveTests state = - serverTestList (nameof MakeOuterBindingRecursive) state defaultConfigDto None (fun server -> [ - testCaseAsync "can make the outer binding recursive when self-referential" <| - CodeFix.check server + serverTestList (nameof MakeOuterBindingRecursive) state defaultConfigDto None (fun server -> + [ testCaseAsync "can make the outer binding recursive when self-referential" + <| CodeFix.check + server """ let mySum xs acc = match xs with @@ -2091,15 +2187,19 @@ let private makeOuterBindingRecursiveTests state = | [] -> acc | _ :: tail -> mySum tail (acc + 1) - """ - ]) + """ ]) let private removeRedundantQualifierTests state = - let config = { defaultConfigDto with SimplifyNameAnalyzer = Some true } - serverTestList (nameof RemoveRedundantQualifier) state config None (fun server -> [ - let selectCodeFix = CodeFix.withTitle RemoveRedundantQualifier.title - testCaseAsync "can remove redundant namespace" <| - CodeFix.check server + let config = + { defaultConfigDto with + SimplifyNameAnalyzer = Some true } + + serverTestList (nameof RemoveRedundantQualifier) state config None (fun server -> + [ let selectCodeFix = CodeFix.withTitle RemoveRedundantQualifier.title + + testCaseAsync "can remove redundant namespace" + <| CodeFix.check + server """ open System let _ = $0System.String.IsNullOrWhiteSpace "foo" @@ -2110,19 +2210,21 @@ let private removeRedundantQualifierTests state = open System let _ = String.IsNullOrWhiteSpace "foo" """ - testCaseAsync "doesn't remove necessary namespace" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't remove necessary namespace" + <| CodeFix.checkNotApplicable + server """ let _ = $0System.String.IsNullOrWhiteSpace "foo" """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private removeUnnecessaryReturnOrYieldTests state = - serverTestList (nameof RemoveUnnecessaryReturnOrYield) state defaultConfigDto None (fun server -> [ - testCaseAsync "can remove return" <| - CodeFix.check server + serverTestList (nameof RemoveUnnecessaryReturnOrYield) state defaultConfigDto None (fun server -> + [ testCaseAsync "can remove return" + <| CodeFix.check + server """ let f x = $0return x @@ -2133,8 +2235,9 @@ let private removeUnnecessaryReturnOrYieldTests state = let f x = x """ - testCaseAsync "can remove return!" <| - CodeFix.check server + testCaseAsync "can remove return!" + <| CodeFix.check + server """ let f x = $0return! x @@ -2145,8 +2248,9 @@ let private removeUnnecessaryReturnOrYieldTests state = let f x = x """ - testCaseAsync "can remove yield" <| - CodeFix.check server + testCaseAsync "can remove yield" + <| CodeFix.check + server """ let f x = $0yield x @@ -2157,8 +2261,9 @@ let private removeUnnecessaryReturnOrYieldTests state = let f x = x """ - testCaseAsync "can remove yield!" <| - CodeFix.check server + testCaseAsync "can remove yield!" + <| CodeFix.check + server """ let f x = $0yield! x @@ -2169,26 +2274,33 @@ let private removeUnnecessaryReturnOrYieldTests state = let f x = x """ - testCaseAsync "doesn't trigger in seq" <| - CodeFix.checkNotApplicable server + testCaseAsync "doesn't trigger in seq" + <| CodeFix.checkNotApplicable + server """ let f x = seq { $0yield x } """ (Diagnostics.acceptAll) - (CodeFix.withTitle (RemoveUnnecessaryReturnOrYield.title "yield")) - ]) + (CodeFix.withTitle (RemoveUnnecessaryReturnOrYield.title "yield")) ]) let private removeUnusedBindingTests state = - let config = { defaultConfigDto with FSIExtraParameters = Some [| "--warnon:1182" |] } - serverTestList (nameof RemoveUnusedBinding) state config None (fun server -> [ - let selectRemoveUnusedBinding = CodeFix.withTitle RemoveUnusedBinding.titleBinding - let selectRemoveUnusedParameter = CodeFix.withTitle RemoveUnusedBinding.titleParameter - let validateDiags = Diagnostics.expectCode "1182" + let config = + { defaultConfigDto with + FSIExtraParameters = Some [| "--warnon:1182" |] } + + serverTestList (nameof RemoveUnusedBinding) state config None (fun server -> + [ let selectRemoveUnusedBinding = CodeFix.withTitle RemoveUnusedBinding.titleBinding + + let selectRemoveUnusedParameter = + CodeFix.withTitle RemoveUnusedBinding.titleParameter - testCaseAsync "can remove unused single character function parameter" <| - CodeFix.check server + let validateDiags = Diagnostics.expectCode "1182" + + testCaseAsync "can remove unused single character function parameter" + <| CodeFix.check + server """ let incr $0i x = 2 """ @@ -2197,8 +2309,10 @@ let private removeUnusedBindingTests state = """ let incr x = 2 """ - testCaseAsync "can remove unused single character function parameter in parens" <| - CodeFix.check server + + testCaseAsync "can remove unused single character function parameter in parens" + <| CodeFix.check + server """ let incr ($0i) x = 2 """ @@ -2207,9 +2321,12 @@ let private removeUnusedBindingTests state = """ let incr x = 2 """ - testCaseAsync "can remove unused binding inside top level" <| + + testCaseAsync "can remove unused binding inside top level" + <| //ENHANCEMENT: remove empty line - CodeFix.check server + CodeFix.check + server """ let container () = let $0incr x = 2 // dummy comment to keep spacing @@ -2219,24 +2336,31 @@ let private removeUnusedBindingTests state = """ let container () = // dummy comment to keep spacing - ()""" - ]) + ()""" ]) let private removeUnusedOpensTests state = - let config = { defaultConfigDto with UnusedOpensAnalyzer = Some true } - serverTestList (nameof RemoveUnusedOpens) state config None (fun server -> [ - let selectCodeFix = CodeFix.withTitle RemoveUnusedOpens.title - testCaseAsync "can remove single unused open" <| - CodeFix.check server + let config = + { defaultConfigDto with + UnusedOpensAnalyzer = Some true } + + serverTestList (nameof RemoveUnusedOpens) state config None (fun server -> + [ let selectCodeFix = CodeFix.withTitle RemoveUnusedOpens.title + + testCaseAsync "can remove single unused open" + <| CodeFix.check + server """ open $0System """ Diagnostics.acceptAll selectCodeFix "" - testCaseAsync "removes just current unused open" <| + + testCaseAsync "removes just current unused open" + <| // unlike VS, `RemoveUnusedOpens` removes just current open (with cursor) and not all unused opens - CodeFix.check server + CodeFix.check + server """ open $0System open System.Text @@ -2246,8 +2370,10 @@ let private removeUnusedOpensTests state = """ open System.Text """ - testCaseAsync "removes just current unused open 2" <| - CodeFix.check server + + testCaseAsync "removes just current unused open 2" + <| CodeFix.check + server """ open System open $0System.Text @@ -2257,8 +2383,10 @@ let private removeUnusedOpensTests state = """ open System """ - testCaseAsync "doesn't remove used open" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't remove used open" + <| CodeFix.checkNotApplicable + server """ open $0System @@ -2266,8 +2394,10 @@ let private removeUnusedOpensTests state = """ Diagnostics.acceptAll selectCodeFix - testCaseAsync "can remove open in nested module" <| - CodeFix.check server + + testCaseAsync "can remove open in nested module" + <| CodeFix.check + server """ module A = module B = @@ -2283,8 +2413,10 @@ let private removeUnusedOpensTests state = () () """ - testCaseAsync "can remove used open in nested module when outer scope opens same open" <| - CodeFix.check server + + testCaseAsync "can remove used open in nested module when outer scope opens same open" + <| CodeFix.check + server """ open System module A = @@ -2304,9 +2436,10 @@ let private removeUnusedOpensTests state = () () """ - //ENHANCEMENT: detect open in outer scope as unused too - itestCaseAsync "can remove used open in outer scope when usage in nested scope has own open" <| - CodeFix.check server + //ENHANCEMENT: detect open in outer scope as unused too + itestCaseAsync "can remove used open in outer scope when usage in nested scope has own open" + <| CodeFix.check + server """ open $0System module A = @@ -2326,24 +2459,32 @@ let private removeUnusedOpensTests state = () () """ - testCaseAsync "doesn't trigger for used open" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for used open" + <| CodeFix.checkNotApplicable + server """ open $0System let x = String.IsNullOrWhiteSpace "" """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private renameUnusedValue state = - let config = { defaultConfigDto with UnusedDeclarationsAnalyzer = Some true } - serverTestList (nameof RenameUnusedValue) state config None (fun server -> [ - let selectReplace = CodeFix.ofKind "refactor" >> CodeFix.withTitle RenameUnusedValue.titleReplace - let selectPrefix = CodeFix.ofKind "refactor" >> CodeFix.withTitle RenameUnusedValue.titlePrefix + let config = + { defaultConfigDto with + UnusedDeclarationsAnalyzer = Some true } + + serverTestList (nameof RenameUnusedValue) state config None (fun server -> + [ let selectReplace = + CodeFix.ofKind "refactor" >> CodeFix.withTitle RenameUnusedValue.titleReplace + + let selectPrefix = + CodeFix.ofKind "refactor" >> CodeFix.withTitle RenameUnusedValue.titlePrefix - testCaseAsync "can replace unused self-reference" <| - CodeFix.check server + testCaseAsync "can replace unused self-reference" + <| CodeFix.check + server """ type MyClass() = member $0this.DoAThing() = () @@ -2354,8 +2495,10 @@ let private renameUnusedValue state = type MyClass() = member _.DoAThing() = () """ - testCaseAsync "can replace unused binding" <| - CodeFix.check server + + testCaseAsync "can replace unused binding" + <| CodeFix.check + server """ let $0six = 6 """ @@ -2364,8 +2507,10 @@ let private renameUnusedValue state = """ let _ = 6 """ - testCaseAsync "can prefix unused binding" <| - CodeFix.check server + + testCaseAsync "can prefix unused binding" + <| CodeFix.check + server """ let $0six = 6 """ @@ -2374,8 +2519,10 @@ let private renameUnusedValue state = """ let _six = 6 """ - testCaseAsync "can replace unused parameter" <| - CodeFix.check server + + testCaseAsync "can replace unused parameter" + <| CodeFix.check + server """ let add one two $0three = one + two """ @@ -2384,8 +2531,10 @@ let private renameUnusedValue state = """ let add one two _ = one + two """ - testCaseAsync "can prefix unused parameter" <| - CodeFix.check server + + testCaseAsync "can prefix unused parameter" + <| CodeFix.check + server """ let add one two $0three = one + two """ @@ -2395,23 +2544,27 @@ let private renameUnusedValue state = let add one two _three = one + two """ - testCaseAsync "doesn't replace function with _" <| - CodeFix.checkNotApplicable server + testCaseAsync "doesn't replace function with _" + <| CodeFix.checkNotApplicable + server """ let $0f _ = () """ (Diagnostics.acceptAll) selectReplace - testCaseAsync "doesn't prefix function with _" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't prefix function with _" + <| CodeFix.checkNotApplicable + server """ let $0f _ = () """ (Diagnostics.acceptAll) selectPrefix - ptestCaseAsync "replacing private variable with _ replaces private too" <| - CodeFix.check server + testCaseAsync "replacing private variable with _ replaces private too" + <| CodeFix.check + server """ let private $0value = 42 """ @@ -2420,17 +2573,19 @@ let private renameUnusedValue state = """ let _ = 42 """ - //TODO: remove this test and enable prev test once FCS includes range for `SynAccess` - testCaseAsync "private variable cannot be replaces with _" <| - CodeFix.checkNotApplicable server + + testCaseAsync "private variable can be replaces with _" + <| CodeFix.checkApplicable + server """ let private $0value = 42 """ (Diagnostics.acceptAll) selectReplace - testCaseAsync "prefixing private variable with _ keeps private" <| - CodeFix.check server + testCaseAsync "prefixing private variable with _ keeps private" + <| CodeFix.check + server """ let private $0value = 42 """ @@ -2440,8 +2595,9 @@ let private renameUnusedValue state = let private _value = 42 """ - testCaseAsync "can replace backticks with _" <| - CodeFix.check server + testCaseAsync "can replace backticks with _" + <| CodeFix.check + server """ let $0``hello world`` = 42 """ @@ -2450,39 +2606,47 @@ let private renameUnusedValue state = """ let _ = 42 """ - testCaseAsync "cannot prefix backticks with _" <| - CodeFix.checkNotApplicable server + + testCaseAsync "cannot prefix backticks with _" + <| CodeFix.checkNotApplicable + server """ let $0``hello world`` = 42 """ (Diagnostics.acceptAll) selectPrefix - testCaseAsync "replace doesn't trigger for function" <| - CodeFix.checkNotApplicable server + testCaseAsync "replace doesn't trigger for function" + <| CodeFix.checkNotApplicable + server """ let $0f _ = () """ (Diagnostics.acceptAll) selectReplace - testCaseAsync "prefix doesn't trigger for function" <| - CodeFix.checkNotApplicable server + + testCaseAsync "prefix doesn't trigger for function" + <| CodeFix.checkNotApplicable + server """ let $0f _ = () """ (Diagnostics.acceptAll) selectPrefix - testCaseAsync "replace doesn't trigger for member" <| - CodeFix.checkNotApplicable server + testCaseAsync "replace doesn't trigger for member" + <| CodeFix.checkNotApplicable + server """ type T() = member _.$0F () = () """ (Diagnostics.acceptAll) selectReplace - testCaseAsync "prefix doesn't trigger for member" <| - CodeFix.checkNotApplicable server + + testCaseAsync "prefix doesn't trigger for member" + <| CodeFix.checkNotApplicable + server """ type T() = member _.$0F () = () @@ -2490,34 +2654,40 @@ let private renameUnusedValue state = (Diagnostics.acceptAll) selectPrefix - testCaseAsync "prefix doesn't trigger for _" <| - CodeFix.checkNotApplicable server + testCaseAsync "prefix doesn't trigger for _" + <| CodeFix.checkNotApplicable + server """ let $0_ = 6 """ (Diagnostics.acceptAll) selectPrefix - testCaseAsync "replace doesn't trigger for _" <| - CodeFix.checkNotApplicable server + testCaseAsync "replace doesn't trigger for _" + <| CodeFix.checkNotApplicable + server """ let $0_ = 6 """ (Diagnostics.acceptAll) - selectReplace - ]) + selectReplace ]) let private replaceWithSuggestionTests state = - serverTestList (nameof ReplaceWithSuggestion) state defaultConfigDto None (fun server -> [ - let selectCodeFix replacement = CodeFix.withTitle (ReplaceWithSuggestion.title replacement) - let validateDiags (diags: Diagnostic[]) = - Diagnostics.expectCode "39" diags - Expect.exists - diags - (fun (d: Diagnostic) -> d.Message.Contains "Maybe you want one of the following:") - "Diagnostic with code 39 should suggest name" - testCaseAsync "can change Min to min" <| - CodeFix.check server + serverTestList (nameof ReplaceWithSuggestion) state defaultConfigDto None (fun server -> + [ let selectCodeFix replacement = + CodeFix.withTitle (ReplaceWithSuggestion.title replacement) + + let validateDiags (diags: Diagnostic[]) = + Diagnostics.expectCode "39" diags + + Expect.exists + diags + (fun (d: Diagnostic) -> d.Message.Contains "Maybe you want one of the following:") + "Diagnostic with code 39 should suggest name" + + testCaseAsync "can change Min to min" + <| CodeFix.check + server """ let x = $0Min(2.0, 1.0) """ @@ -2526,30 +2696,35 @@ let private replaceWithSuggestionTests state = """ let x = min(2.0, 1.0) """ - testList "can get multiple suggestions for flout" [ - testCaseAsync "can change flout to float" <| - CodeFix.check server - """ + + testList + "can get multiple suggestions for flout" + [ testCaseAsync "can change flout to float" + <| CodeFix.check + server + """ let x = $0flout 2 """ - validateDiags - (selectCodeFix "float") - """ + validateDiags + (selectCodeFix "float") + """ let x = float 2 """ - testCaseAsync "can change flout to float32" <| - CodeFix.check server - """ + testCaseAsync "can change flout to float32" + <| CodeFix.check + server + """ let x = $0flout 2 """ - validateDiags - (selectCodeFix "float32") - """ + validateDiags + (selectCodeFix "float32") + """ let x = float32 2 - """ - ] - testCaseAsync "can change flout to float in var type" <| - CodeFix.check server + """ ] + + testCaseAsync "can change flout to float in var type" + <| CodeFix.check + server """ let x: $0flout = 2.0 """ @@ -2558,8 +2733,10 @@ let private replaceWithSuggestionTests state = """ let x: float = 2.0 """ - testCaseAsync "can change namespace in open" <| - CodeFix.check server + + testCaseAsync "can change namespace in open" + <| CodeFix.check + server """ open System.Text.$0RegularEcpressions """ @@ -2568,8 +2745,10 @@ let private replaceWithSuggestionTests state = """ open System.Text.RegularExpressions """ - testCaseAsync "can change type in type constructor" <| - CodeFix.check server + + testCaseAsync "can change type in type constructor" + <| CodeFix.check + server """ open System.Text.RegularExpressions let x = $0Regec() @@ -2580,8 +2759,10 @@ let private replaceWithSuggestionTests state = open System.Text.RegularExpressions let x = Regex() """ - testCaseAsync "can replace identifier in double-backticks" <| - CodeFix.check server + + testCaseAsync "can replace identifier in double-backticks" + <| CodeFix.check + server """ let ``hello world`` = 2 let x = ``$0hello word`` @@ -2592,8 +2773,10 @@ let private replaceWithSuggestionTests state = let ``hello world`` = 2 let x = ``hello world`` """ - testCaseAsync "can add double-backticks" <| - CodeFix.check server + + testCaseAsync "can add double-backticks" + <| CodeFix.check + server """ let ``hello world`` = 2 let x = $0helloword @@ -2603,37 +2786,44 @@ let private replaceWithSuggestionTests state = """ let ``hello world`` = 2 let x = ``hello world`` - """ - ]) + """ ]) let private resolveNamespaceTests state = - let config = { defaultConfigDto with ResolveNamespaces = Some true } - serverTestList (nameof ResolveNamespace) state config None (fun server -> [ - let selectCodeFix = CodeFix.matching (fun ca -> ca.Title.StartsWith "open") - testCaseAsync "doesn't fail when target not in last line" <| - CodeFix.checkApplicable server + let config = + { defaultConfigDto with + ResolveNamespaces = Some true } + + serverTestList (nameof ResolveNamespace) state config None (fun server -> + [ let selectCodeFix = CodeFix.matching (fun ca -> ca.Title.StartsWith "open") + + testCaseAsync "doesn't fail when target not in last line" + <| CodeFix.checkApplicable + server """ let x = $0Min(2.0, 1.0) - """ // Note: new line at end! + """ // Note: new line at end! (Diagnostics.log >> Diagnostics.acceptAll) (CodeFix.log >> selectCodeFix >> Array.take 1) - testCaseAsync "doesn't fail when target in last line" <| - CodeFix.checkApplicable server - "let x = $0Min(2.0, 1.0)" // Note: No new line at end! + + testCaseAsync "doesn't fail when target in last line" + <| CodeFix.checkApplicable + server + "let x = $0Min(2.0, 1.0)" // Note: No new line at end! (Diagnostics.log >> Diagnostics.acceptAll) (CodeFix.log >> selectCodeFix >> Array.take 1) - testCaseAsync "place open in module correctly when having additional modules" + + testCaseAsync "place open in module correctly when having additional modules" <| CodeFix.check - server - """ + server + """ module Foo = open Microsoft let foo = Date$0Time.Now """ - (Diagnostics.log >> Diagnostics.acceptAll) - selectCodeFix - """ + (Diagnostics.log >> Diagnostics.acceptAll) + selectCodeFix + """ module Foo = open Microsoft open System @@ -2642,16 +2832,16 @@ module Foo = """ - testCaseAsync "place open in module correctly without any modules" + testCaseAsync "place open in module correctly without any modules" <| CodeFix.check - server - """ + server + """ module Foo = let foo = $0DateTime.Now """ - (Diagnostics.log >> Diagnostics.acceptAll) - selectCodeFix - """ + (Diagnostics.log >> Diagnostics.acceptAll) + selectCodeFix + """ module Foo = open System let foo = DateTime.Now @@ -2659,35 +2849,37 @@ module Foo = - testCaseAsync "With attribute" + testCaseAsync "With attribute" <| CodeFix.check - server - """ + server + """ [] module Foo = let foo = $0DateTime.Now """ - (Diagnostics.log >> Diagnostics.acceptAll) - selectCodeFix - """ + (Diagnostics.log >> Diagnostics.acceptAll) + selectCodeFix + """ [] module Foo = open System let foo = DateTime.Now """ - //TODO: Implement & unify with `Completion.AutoOpen` (`CompletionTests.fs`) - // Issues: - // * Complex because of nesting modules (-> where to open) - // * Different open locations of CodeFix and AutoOpen - ]) + //TODO: Implement & unify with `Completion.AutoOpen` (`CompletionTests.fs`) + // Issues: + // * Complex because of nesting modules (-> where to open) + // * Different open locations of CodeFix and AutoOpen + ]) let private useMutationWhenValueIsMutableTests state = - serverTestList (nameof UseMutationWhenValueIsMutable) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle UseMutationWhenValueIsMutable.title - testCaseAsync "can replace = with <- when cursor on =" <| - CodeFix.check server + serverTestList (nameof UseMutationWhenValueIsMutable) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle UseMutationWhenValueIsMutable.title + + testCaseAsync "can replace = with <- when cursor on =" + <| CodeFix.check + server """ let _ = let mutable v = 42 @@ -2702,8 +2894,10 @@ let private useMutationWhenValueIsMutableTests state = v <- 5 v """ - testCaseAsync "can replace = with <- when cursor on variable" <| - CodeFix.check server + + testCaseAsync "can replace = with <- when cursor on variable" + <| CodeFix.check + server """ let _ = let mutable v = 42 @@ -2718,8 +2912,10 @@ let private useMutationWhenValueIsMutableTests state = v <- 5 v """ - testCaseAsync "doesn't suggest fix when = is comparison" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't suggest fix when = is comparison" + <| CodeFix.checkNotApplicable + server """ let _ = let mutable v = 42 @@ -2727,8 +2923,10 @@ let private useMutationWhenValueIsMutableTests state = """ Diagnostics.acceptAll selectCodeFix - testCaseAsync "doesn't suggest fix when variable is not mutable" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't suggest fix when variable is not mutable" + <| CodeFix.checkNotApplicable + server """ let _ = let v = 42 @@ -2736,30 +2934,32 @@ let private useMutationWhenValueIsMutableTests state = v """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private useTripleQuotedInterpolationTests state = // blocked by FCS 43.7.200 - AST changes - pserverTestList (nameof UseTripleQuotedInterpolation) state defaultConfigDto None (fun server -> [ - testCaseAsync "converts erroring single-quoted interpolation to triple-quoted" <| - CodeFix.check server + pserverTestList (nameof UseTripleQuotedInterpolation) state defaultConfigDto None (fun server -> + [ testCaseAsync "converts erroring single-quoted interpolation to triple-quoted" + <| CodeFix.check + server """ let a = $":^) {if true then $0"y" else "n"} d" """ (Diagnostics.expectCode "3373") - (CodeFix.ofKind "quickfix" >> CodeFix.withTitle UseTripleQuotedInterpolation.title) + (CodeFix.ofKind "quickfix" + >> CodeFix.withTitle UseTripleQuotedInterpolation.title) // cannot use triple quotes string here: ends with `"""` -> cannot use in string @" let a = $"""""":^) {if true then ""y"" else ""n""} d"""""" - " - ]) + " ]) let private wrapExpressionInParenthesesTests state = - serverTestList (nameof WrapExpressionInParentheses) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle WrapExpressionInParentheses.title - testCaseAsync "can add parenthesize expression" <| - CodeFix.check server + serverTestList (nameof WrapExpressionInParentheses) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle WrapExpressionInParentheses.title + + testCaseAsync "can add parenthesize expression" + <| CodeFix.check + server """ printfn "%b" System.String.$0IsNullOrWhiteSpace("foo") """ @@ -2768,14 +2968,15 @@ let private wrapExpressionInParenthesesTests state = """ printfn "%b" (System.String.IsNullOrWhiteSpace("foo")) """ - testCaseAsync "doesn't trigger for expression in parens" <| - CodeFix.checkNotApplicable server + + testCaseAsync "doesn't trigger for expression in parens" + <| CodeFix.checkNotApplicable + server """ printfn "%b" (System.String.$0IsNullOrWhiteSpace("foo")) """ Diagnostics.acceptAll - selectCodeFix - ]) + selectCodeFix ]) let private removeRedundantAttributeSuffixTests state = serverTestList (nameof RemoveRedundantAttributeSuffix) state defaultConfigDto None (fun server -> @@ -2874,10 +3075,12 @@ let private removeRedundantAttributeSuffixTests state = """ ]) let private removePatternArgumentTests state = - serverTestList (nameof RemovePatternArgument) state defaultConfigDto None (fun server -> [ - let selectCodeFix = CodeFix.withTitle RemovePatternArgument.title - testCaseAsync "Literal pattern qualified single parameter" <| - CodeFix.check server + serverTestList (nameof RemovePatternArgument) state defaultConfigDto None (fun server -> + [ let selectCodeFix = CodeFix.withTitle RemovePatternArgument.title + + testCaseAsync "Literal pattern qualified single parameter" + <| CodeFix.check + server """ type E = | A = 1 @@ -2895,8 +3098,9 @@ let private removePatternArgumentTests state = let (E.A) = E.A """ - testCaseAsync "Local literal pattern qualified match parens parameter" <| - CodeFix.check server + testCaseAsync "Local literal pattern qualified match parens parameter" + <| CodeFix.check + server """ type E = | A = 1 @@ -2916,8 +3120,9 @@ let private removePatternArgumentTests state = | (E.A) -> () """ - testCaseAsync "Local literal pattern qualified single parameter" <| - CodeFix.check server + testCaseAsync "Local literal pattern qualified single parameter" + <| CodeFix.check + server """ type E = | A = 1 @@ -2939,8 +3144,9 @@ let private removePatternArgumentTests state = () """ - testCaseAsync "Local literal constant pattern qualified parameter" <| - CodeFix.check server + testCaseAsync "Local literal constant pattern qualified parameter" + <| CodeFix.check + server """ let [] A = 1 @@ -2956,8 +3162,9 @@ let private removePatternArgumentTests state = | A -> () """ - testCaseAsync "Local literal constant pattern qualified parens parameter" <| - CodeFix.check server + testCaseAsync "Local literal constant pattern qualified parens parameter" + <| CodeFix.check + server """ let [] A = 1 @@ -2973,8 +3180,9 @@ let private removePatternArgumentTests state = | (A) -> () """ - testCaseAsync "Local match qualified single parameter" <| - CodeFix.check server + testCaseAsync "Local match qualified single parameter" + <| CodeFix.check + server """ match None with | Option.None x$0 -> () @@ -2986,8 +3194,9 @@ let private removePatternArgumentTests state = | Option.None -> () """ - testCaseAsync "Local match qualified single parens parameter" <| - CodeFix.check server + testCaseAsync "Local match qualified single parens parameter" + <| CodeFix.check + server """ match None with | (Option.None x$0) -> () @@ -2999,8 +3208,9 @@ let private removePatternArgumentTests state = | (Option.None) -> () """ - testCaseAsync "Qualified single parameter" <| - CodeFix.check server + testCaseAsync "Qualified single parameter" + <| CodeFix.check + server """ let (Option.None x$0) = None """ @@ -3010,8 +3220,9 @@ let private removePatternArgumentTests state = let (Option.None) = None """ - testCaseAsync "Local single parameter" <| - CodeFix.check server + testCaseAsync "Local single parameter" + <| CodeFix.check + server """ do let (Option.None x$0) = None @@ -3025,8 +3236,9 @@ let private removePatternArgumentTests state = () """ - testCaseAsync "Local two match parameters" <| - CodeFix.check server + testCaseAsync "Local two match parameters" + <| CodeFix.check + server """ match None with | None x$0 y -> () @@ -3038,8 +3250,9 @@ let private removePatternArgumentTests state = | None -> () """ - testCaseAsync "Local two match parens parameters" <| - CodeFix.check server + testCaseAsync "Local two match parens parameters" + <| CodeFix.check + server """ match None with | None (x$0 y) -> () @@ -3051,8 +3264,9 @@ let private removePatternArgumentTests state = | None -> () """ - testCaseAsync "Local two parameter" <| - CodeFix.check server + testCaseAsync "Local two parameter" + <| CodeFix.check + server """ do let (Option.None x$0 y) = None @@ -3066,8 +3280,9 @@ let private removePatternArgumentTests state = () """ - testCaseAsync "Single parameter" <| - CodeFix.check server + testCaseAsync "Single parameter" + <| CodeFix.check + server """ let (None x$0) = None """ @@ -3077,8 +3292,9 @@ let private removePatternArgumentTests state = let (None) = None """ - testCaseAsync "Two parameters" <| - CodeFix.check server + testCaseAsync "Two parameters" + <| CodeFix.check + server """ let (None x$0 y) = None """ @@ -3086,53 +3302,53 @@ let private removePatternArgumentTests state = selectCodeFix """ let (None) = None - """ - ]) - -let tests state = testList "CodeFix-tests" [ - HelpersTests.tests - - AddExplicitTypeAnnotationTests.tests state - ToInterpolatedStringTests.tests state - ToInterpolatedStringTests.unavailableTests state - addMissingEqualsToTypeDefinitionTests state - addMissingFunKeywordTests state - addMissingInstanceMemberTests state - addMissingRecKeywordTests state - addMissingXmlDocumentationTests state - addNewKeywordToDisposableConstructorInvocationTests state - addTypeToIndeterminateValueTests state - changeDerefBangToValueTests state - changeDowncastToUpcastTests state - changeEqualsInFieldTypeToColonTests state - changePrefixNegationToInfixSubtractionTests state - changeRefCellDerefToNotTests state - changeTypeOfNameToNameOfTests state - convertBangEqualsToInequalityTests state - convertCSharpLambdaToFSharpLambdaTests state - convertDoubleEqualsToSingleEqualsTests state - convertInvalidRecordToAnonRecordTests state - convertPositionalDUToNamedTests state - convertTripleSlashCommentToXmlTaggedDocTests state - addPrivateAccessModifierTests state - GenerateAbstractClassStubTests.tests state - generateRecordStubTests state - generateUnionCasesTests state - generateXmlDocumentationTests state - ImplementInterfaceTests.tests state - makeDeclarationMutableTests state - makeOuterBindingRecursiveTests state - removeRedundantQualifierTests state - removeUnnecessaryReturnOrYieldTests state - removeUnusedBindingTests state - removeUnusedOpensTests state - RenameParamToMatchSignatureTests.tests state - renameUnusedValue state - replaceWithSuggestionTests state - resolveNamespaceTests state - useMutationWhenValueIsMutableTests state - useTripleQuotedInterpolationTests state - wrapExpressionInParenthesesTests state - removeRedundantAttributeSuffixTests state - removePatternArgumentTests state -] + """ ]) + +let tests state = + testList + "CodeFix-tests" + [ HelpersTests.tests + + AddExplicitTypeAnnotationTests.tests state + ToInterpolatedStringTests.tests state + ToInterpolatedStringTests.unavailableTests state + addMissingEqualsToTypeDefinitionTests state + addMissingFunKeywordTests state + addMissingInstanceMemberTests state + addMissingRecKeywordTests state + addMissingXmlDocumentationTests state + addNewKeywordToDisposableConstructorInvocationTests state + addTypeToIndeterminateValueTests state + changeDerefBangToValueTests state + changeDowncastToUpcastTests state + changeEqualsInFieldTypeToColonTests state + changePrefixNegationToInfixSubtractionTests state + changeRefCellDerefToNotTests state + changeTypeOfNameToNameOfTests state + convertBangEqualsToInequalityTests state + convertCSharpLambdaToFSharpLambdaTests state + convertDoubleEqualsToSingleEqualsTests state + convertInvalidRecordToAnonRecordTests state + convertPositionalDUToNamedTests state + convertTripleSlashCommentToXmlTaggedDocTests state + addPrivateAccessModifierTests state + GenerateAbstractClassStubTests.tests state + generateRecordStubTests state + generateUnionCasesTests state + generateXmlDocumentationTests state + ImplementInterfaceTests.tests state + makeDeclarationMutableTests state + makeOuterBindingRecursiveTests state + removeRedundantQualifierTests state + removeUnnecessaryReturnOrYieldTests state + removeUnusedBindingTests state + removeUnusedOpensTests state + RenameParamToMatchSignatureTests.tests state + renameUnusedValue state + replaceWithSuggestionTests state + resolveNamespaceTests state + useMutationWhenValueIsMutableTests state + useTripleQuotedInterpolationTests state + wrapExpressionInParenthesesTests state + removeRedundantAttributeSuffixTests state + removePatternArgumentTests state ]