|
| 1 | +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. |
| 2 | + |
| 3 | +namespace Microsoft.VisualStudio.FSharp.Editor |
| 4 | + |
| 5 | +open System |
| 6 | +open System.Collections.Immutable |
| 7 | +open System.Composition |
| 8 | +open System.Threading.Tasks |
| 9 | + |
| 10 | +open Microsoft.CodeAnalysis |
| 11 | +open Microsoft.CodeAnalysis.Text |
| 12 | +open Microsoft.CodeAnalysis.CodeFixes |
| 13 | + |
| 14 | +open Microsoft.FSharp.Compiler |
| 15 | +open Microsoft.FSharp.Compiler.SourceCodeServices |
| 16 | +open Microsoft.VisualStudio.FSharp.Editor.SymbolHelpers |
| 17 | +open Microsoft.FSharp.Compiler.SourceCodeServices.Keywords |
| 18 | + |
| 19 | +[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "FSharpRenameParamToMatchSignature"); Shared>] |
| 20 | +type internal FSharpRenameParamToMatchSignature |
| 21 | + [<ImportingConstructor>] |
| 22 | + ( |
| 23 | + checkerProvider: FSharpCheckerProvider, |
| 24 | + projectInfoManager: FSharpProjectOptionsManager |
| 25 | + ) = |
| 26 | + |
| 27 | + inherit CodeFixProvider() |
| 28 | + static let userOpName = "RenameParamToMatchSignature" |
| 29 | + let fixableDiagnosticIds = ["FS3218"] |
| 30 | + |
| 31 | + |
| 32 | + override __.FixableDiagnosticIds = Seq.toImmutableArray fixableDiagnosticIds |
| 33 | + |
| 34 | + override __.RegisterCodeFixesAsync context : Task = |
| 35 | + asyncMaybe { |
| 36 | + match context.Diagnostics |> Seq.filter (fun x -> fixableDiagnosticIds |> List.contains x.Id) |> Seq.toList with |
| 37 | + | [diagnostic] -> |
| 38 | + let message = diagnostic.GetMessage() |
| 39 | + let parts = System.Text.RegularExpressions.Regex.Match(message, ".+'(.+)'.+'(.+)'.+") |
| 40 | + if parts.Success then |
| 41 | + |
| 42 | + let diagnostics = ImmutableArray.Create diagnostic |
| 43 | + let suggestion = parts.Groups.[1].Value |
| 44 | + let replacement = QuoteIdentifierIfNeeded suggestion |
| 45 | + let computeChanges() = |
| 46 | + asyncMaybe { |
| 47 | + let document = context.Document |
| 48 | + let! cancellationToken = Async.CancellationToken |> liftAsync |
| 49 | + let! sourceText = document.GetTextAsync(cancellationToken) |
| 50 | + let! symbolUses = getSymbolUsesOfSymbolAtLocationInDocument (document, context.Span.Start, projectInfoManager, checkerProvider.Checker, userOpName) |
| 51 | + let changes = |
| 52 | + [| for symbolUse in symbolUses do |
| 53 | + match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) with |
| 54 | + | None -> () |
| 55 | + | Some span -> |
| 56 | + let textSpan = Tokenizer.fixupSpan(sourceText, span) |
| 57 | + yield TextChange(textSpan, replacement) |] |
| 58 | + return changes |
| 59 | + } |
| 60 | + let title = FSComp.SR.replaceWithSuggestion suggestion |
| 61 | + let codefix = createTextChangeCodeFix(title, context, computeChanges) |
| 62 | + context.RegisterCodeFix(codefix, diagnostics) |
| 63 | + | _ -> () |
| 64 | + } |> Async.Ignore |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken) |
0 commit comments