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/paket.dependencies b/paket.dependencies index 35b9daac5..e34f8d8f7 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -14,10 +14,10 @@ lowest_matching: true nuget BenchmarkDotNet 0.13.5 nuget Fantomas.Client >= 0.9 nuget FSharp.Compiler.Service >= 43.7.400 -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 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 diff --git a/paket.lock b/paket.lock index e4020cb5a..5c1a1cada 100644 --- a/paket.lock +++ b/paket.lock @@ -134,25 +134,25 @@ NUGET FSharp.Core (>= 6.0) Newtonsoft.Json (>= 13.0.1) StreamJsonRpc (>= 2.10.44) - Ionide.ProjInfo (0.62.0-nightly001) - FSharp.Core (>= 7.0.400-beta.23322.4 < 7.1.0-prerelease) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.Sln (>= 0.62.0-nightly001) - 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.6.3) - 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.62.0-nightly001) - FSharp.Compiler.Service (>= 43.7.400-preview.23322.4 < 43.8.0-prerelease) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - FSharp.Core (>= 7.0.400-beta.23322.4 < 7.1.0-prerelease) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo (>= 0.62.0-nightly001) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.ProjectSystem (0.62.0-nightly001) - FSharp.Compiler.Service (>= 43.7.400-preview.23322.4 < 43.8.0-prerelease) - 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 (>= 7.0.400-beta.23322.4 < 7.1.0-prerelease) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo (>= 0.62.0-nightly001) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.FCS (>= 0.62.0-nightly001) - restriction: || (== net6.0) (== net7.0) (&& (== netstandard2.0) (>= net6.0)) (&& (== netstandard2.1) (>= net6.0)) - Ionide.ProjInfo.Sln (>= 0.62.0-nightly001) - 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)) diff --git a/src/FsAutoComplete.Core/Commands.fs b/src/FsAutoComplete.Core/Commands.fs index 9c4393a00..10eb5cea2 100644 --- a/src/FsAutoComplete.Core/Commands.fs +++ b/src/FsAutoComplete.Core/Commands.fs @@ -922,7 +922,6 @@ 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 @@ -2048,7 +2047,7 @@ type Commands match valData with | SynValData(memberFlags = Some({ MemberKind = SynMemberKind.PropertyGet })) | SynValData(memberFlags = Some({ MemberKind = SynMemberKind.PropertySet })) - | SynValData(memberFlags = Some({ MemberKind = SynMemberKind.PropertyGetSet })) -> Some true + | SynValData(memberFlags = Some({ MemberKind = SynMemberKind.PropertyGetSet })) -> None | _ -> Some false | _ -> defaultTraverse synBinding @@ -2145,17 +2144,17 @@ type Commands -> 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 true + 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 true + Some false | _ -> None) | _ -> None) | _ -> None) 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/Lexer.fs b/src/FsAutoComplete.Core/Lexer.fs index 500724d99..cc7d503b3 100644 --- a/src/FsAutoComplete.Core/Lexer.fs +++ b/src/FsAutoComplete.Core/Lexer.fs @@ -41,22 +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 langVersion = - args - |> Array.tryPick (fun arg -> - if arg.StartsWith "--langversion:" then - Some(arg.[14..]) - else - None) + 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", langVersion) let lineTokenizer = sourceTokenizer.CreateLineTokenizer lineStr let rec loop lexState acc = 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 ee61f8fd4..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,49 @@ 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 = let tryGetParseResultsForFile filePath pos = @@ -1779,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 diff --git a/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs b/src/FsAutoComplete/LspServers/FsAutoComplete.Lsp.fs index edf269a69..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, diff --git a/test/FsAutoComplete.Tests.Lsp/CodeFixTests/Tests.fs b/test/FsAutoComplete.Tests.Lsp/CodeFixTests/Tests.fs index 207d1f546..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 - testCaseAsync "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,16 +2573,19 @@ let private renameUnusedValue state = """ let _ = 42 """ - testCaseAsync "private variable can be replaces with _" <| - CodeFix.checkApplicable 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 """ @@ -2439,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 """ @@ -2449,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 () = () @@ -2489,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) """ @@ -2525,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 """ @@ -2557,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 """ @@ -2567,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() @@ -2579,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`` @@ -2591,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 @@ -2602,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 @@ -2641,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 @@ -2658,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 @@ -2701,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 @@ -2717,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 @@ -2726,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 @@ -2735,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") """ @@ -2767,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 -> @@ -2873,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 @@ -2894,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 @@ -2915,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 @@ -2938,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 @@ -2955,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 @@ -2972,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 -> () @@ -2985,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) -> () @@ -2998,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 """ @@ -3009,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 @@ -3024,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 -> () @@ -3037,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) -> () @@ -3050,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 @@ -3065,8 +3280,9 @@ let private removePatternArgumentTests state = () """ - testCaseAsync "Single parameter" <| - CodeFix.check server + testCaseAsync "Single parameter" + <| CodeFix.check + server """ let (None x$0) = None """ @@ -3076,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 """ @@ -3085,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 ]