From d1773e7f68d23d5705530d31bc443f1a0ef01fed Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Wed, 22 Nov 2023 11:13:01 -0500 Subject: [PATCH] =?UTF-8?q?Make=20paren=20tests=20run=202=E2=80=933=C3=97?= =?UTF-8?q?=20as=20fast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * This optimization could in theory be used for all tests in this project if we set up some kind of solution cache keyed by project & editor settings, but it looks like it would require some refactoring in RoslynTestHelpers. --- .../CodeFixes/CodeFixTestFramework.fs | 4 +- .../RemoveUnnecessaryParenthesesTests.fs | 46 +++++++++++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/CodeFixTestFramework.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/CodeFixTestFramework.fs index 0a0ca440236..3818f89a0d9 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/CodeFixTestFramework.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/CodeFixTestFramework.fs @@ -220,7 +220,7 @@ module Xunit = /// /// Thrown if a code fix is applied. /// - let expectNoFix (tryFix: string -> Task) code = + let expectNoFix (tryFix: string -> CancellableTask) code = cancellableTask { match! tryFix code with | None -> () @@ -246,7 +246,7 @@ module Xunit = /// /// Thrown if the generated fix does not match the expected fixed code. /// - let expectFix tryFix code fixedCode = + let expectFix (tryFix: string -> CancellableTask) code fixedCode = if code = fixedCode then expectNoFix tryFix code else diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs index 806a1e4d18b..94da8b34540 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveUnnecessaryParenthesesTests.fs @@ -3,7 +3,8 @@ module FSharp.Editor.Tests.CodeFixes.RemoveUnnecessaryParenthesesTests open System.Text -open FSharp.Compiler.Text +open FSharp.Editor.Tests.Helpers +open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.Text open Microsoft.VisualStudio.FSharp.Editor open Microsoft.VisualStudio.FSharp.Editor.CancellableTasks @@ -13,17 +14,45 @@ open CodeFixTestFramework [] module private TopLevel = let private fixer = FSharpRemoveUnnecessaryParenthesesCodeFixProvider() - let private fixAllProvider = fixer.RegisterFsharpFixAll() + + // It is much (2–3×) faster to reuse the same solution + // rather than creating a new one for each test. + // Unfortunately, it is not safe to reuse the same solution across + // tests that may set different project or editor options, + // because they may run concurrently on other threads, + // and the in-memory settings store used for tests is global, + // so we restrict this optimization to this file. + let private sln, projId = + let projInfo = + RoslynTestHelpers.CreateProjectInfo (ProjectId.CreateNewId()) "C:\\test.fsproj" [] + + let sln = RoslynTestHelpers.CreateSolution [ projInfo ] + + let projectOptions = + { RoslynTestHelpers.DefaultProjectOptions with + OtherOptions = + [| + "--targetprofile:netcore" // without this lib some symbols are not loaded + "--nowarn:3384" // The .NET SDK for this script could not be determined + |] + } + + RoslynTestHelpers.SetProjectOptions projInfo.Id sln projectOptions + + RoslynTestHelpers.SetEditorOptions + sln + { CodeFixesOptions.Default with + RemoveParens = true + } + + sln, projInfo.Id let private tryFix (code: string) = cancellableTask { - let mode = - WithSettings - { CodeFixesOptions.Default with - RemoveParens = true - } + let document = + let docInfo = RoslynTestHelpers.CreateDocumentInfo projId "C:\\test.fs" code + (sln.AddDocument docInfo).GetDocument docInfo.Id - let document = Document.create mode code let sourceText = SourceText.From code let! diagnostics = FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document, DiagnosticsType.Syntax) @@ -34,7 +63,6 @@ module private TopLevel = |> ValueOption.either (fixer :> IFSharpCodeFixProvider).GetCodeFixIfAppliesAsync (CancellableTask.singleton ValueNone) |> CancellableTask.map (ValueOption.map (TestCodeFix.ofFSharpCodeFix sourceText) >> ValueOption.toOption) } - |> CancellableTask.startWithoutCancellation let expectFix = expectFix tryFix