From f35fa1a176a064cac55bdb8868cbefdbc2406f0d Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 8 Nov 2022 16:06:30 +0100 Subject: [PATCH] New codefix provider to remove superflous binding for a Union case that has 0 fields. (#14267) --- .../FSharp.Editor/CodeFix/CodeFixHelpers.fs | 15 ++++++ ...SuperflousCaptureForUnionCaseWithNoData.fs | 50 +++++++++++++++++++ .../src/FSharp.Editor/FSharp.Editor.fsproj | 1 + 3 files changed, 66 insertions(+) create mode 100644 vsintegration/src/FSharp.Editor/CodeFix/RemoveSuperflousCaptureForUnionCaseWithNoData.fs diff --git a/vsintegration/src/FSharp.Editor/CodeFix/CodeFixHelpers.fs b/vsintegration/src/FSharp.Editor/CodeFix/CodeFixHelpers.fs index fb311ae60..f8362e387 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/CodeFixHelpers.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/CodeFixHelpers.fs @@ -22,3 +22,18 @@ module internal CodeFixHelpers = | Some textChanges -> return context.Document.WithText(sourceText.WithChanges(textChanges)) } |> RoslynHelpers.StartAsyncAsTask(cancellationToken)), title) + +[] +module internal CodeFixExtensions = + type CodeFixProvider with + member this.GetPrunedDiagnostics(context: CodeFixContext) = + context.Diagnostics.RemoveAll(fun x -> this.FixableDiagnosticIds.Contains(x.Id) |> not) + + member this.RegisterFix(context: CodeFixContext, fixName, fixChange) = + let replaceCodeFix = + CodeFixHelpers.createTextChangeCodeFix( + fixName, + context, + (fun () -> asyncMaybe.Return [| fixChange |])) + context.RegisterCodeFix(replaceCodeFix, this.GetPrunedDiagnostics(context)) + diff --git a/vsintegration/src/FSharp.Editor/CodeFix/RemoveSuperflousCaptureForUnionCaseWithNoData.fs b/vsintegration/src/FSharp.Editor/CodeFix/RemoveSuperflousCaptureForUnionCaseWithNoData.fs new file mode 100644 index 000000000..ab39b48fc --- /dev/null +++ b/vsintegration/src/FSharp.Editor/CodeFix/RemoveSuperflousCaptureForUnionCaseWithNoData.fs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Editor + +open System +open System.Composition +open System.Threading.Tasks + +open Microsoft.CodeAnalysis.Text +open Microsoft.CodeAnalysis.CodeFixes + +open FSharp.Compiler +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Symbols +open FSharp.Compiler.Syntax +open FSharp.Compiler.EditorServices + +[] +type internal RemoveSuperflousCaptureForUnionCaseWithNoDataProvider + [] + ( + ) = + + inherit CodeFixProvider() + + override _.FixableDiagnosticIds = Seq.toImmutableArray ["FS0725";"FS3548"] + + override this.RegisterCodeFixesAsync context : Task = + asyncMaybe { + do! Option.guard context.Document.Project.IsFSharpCodeFixesUnusedDeclarationsEnabled + + let document = context.Document + let! sourceText = document.GetTextAsync(context.CancellationToken) + let! _, checkResults = document.GetFSharpParseAndCheckResultsAsync(nameof(RemoveSuperflousCaptureForUnionCaseWithNoDataProvider)) |> liftAsync + let m = RoslynHelpers.TextSpanToFSharpRange(document.FilePath, context.Span, sourceText) + let classifications = checkResults.GetSemanticClassification(Some m) + let unionCaseItem = + classifications + |> Array.tryFind (fun c -> c.Type = SemanticClassificationType.UnionCase) + + match unionCaseItem with + | None -> () + | Some unionCaseItem -> + // The error/warning captures entire pattern match, like "Ns.Type.DuName bindingName". We want to keep type info when suggesting a replacement, and only remove "bindingName". + let typeInfoLength = unionCaseItem.Range.EndColumn - m.StartColumn + let reminderSpan = new TextSpan(context.Span.Start + typeInfoLength, context.Span.Length - typeInfoLength) + this.RegisterFix(context, SR.RemoveUnusedBinding(), TextChange(reminderSpan, "")) + } + |> Async.Ignore + |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken) diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index b0b4cae70..db217723e 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -114,6 +114,7 @@ + -- GitLab