diff --git a/CodeFix/UseMutationWhenValueIsMutable.fs b/CodeFix/UseMutationWhenValueIsMutable.fs new file mode 100644 index 00000000000..67003759d0a --- /dev/null +++ b/CodeFix/UseMutationWhenValueIsMutable.fs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Editor + +open System.Composition +open System.Threading +open System.Threading.Tasks + +open Microsoft.CodeAnalysis.Text +open Microsoft.CodeAnalysis.CodeFixes + +open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.Range + +[] +type internal FSharpUseMutationWhenValueIsMutableFixProvider + [] + ( + checkerProvider: FSharpCheckerProvider, + projectInfoManager: FSharpProjectOptionsManager + ) = + inherit CodeFixProvider() + + static let userOpName = "UseMutationWhenValueIsMutable" + + let fixableDiagnosticIds = set ["FS0020"] + + override _.FixableDiagnosticIds = Seq.toImmutableArray fixableDiagnosticIds + + override _.RegisterCodeFixesAsync context : Task = + asyncMaybe { + let diagnostics = + context.Diagnostics + |> Seq.filter (fun x -> fixableDiagnosticIds |> Set.contains x.Id) + |> Seq.toImmutableArray + + let document = context.Document + do! Option.guard (not(isSignatureFile document.FilePath)) + let position = context.Span.Start + let checker = checkerProvider.Checker + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, CancellationToken.None, userOpName) + let! sourceText = document.GetTextAsync () |> liftTaskAsync + let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + let textLine = sourceText.Lines.GetLineFromPosition position + let textLinePos = sourceText.Lines.GetLinePosition position + let fcsTextLineNumber = Line.fromZ textLinePos.Line + let! _, _, checkFileResults = checker.ParseAndCheckDocument (document, projectOptions, sourceText=sourceText, userOpName=userOpName) + let! lexerSymbol = Tokenizer.getSymbolAtPosition (document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) + let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, lexerSymbol.Ident.idRange.EndColumn, textLine.ToString(), lexerSymbol.FullIsland) + + match symbolUse.Symbol with + | :? FSharpMemberOrFunctionOrValue as mfv when mfv.IsValue && mfv.IsMutable -> + let title = SR.UseMutationWhenValueIsMutable() + let! symbolSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) + let mutable pos = symbolSpan.End + let mutable ch = sourceText.GetSubText(pos).ToString() + + // We're looking for the possibly erroneous '=' + while pos <= context.Span.Length && ch <> "=" do + pos <- pos + 1 + ch <- sourceText.GetSubText(pos).ToString() + + let codeFix = + CodeFixHelpers.createTextChangeCodeFix( + title, + context, + (fun () -> asyncMaybe.Return [| TextChange(TextSpan(pos + 1, 1), "<-") |])) + + context.RegisterCodeFix(codeFix, diagnostics) + | _ -> () + } + |> Async.Ignore + |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken) \ No newline at end of file diff --git a/FSharp.Editor.fsproj b/FSharp.Editor.fsproj index 7ee5ebb362e..7f77c679fdb 100644 --- a/FSharp.Editor.fsproj +++ b/FSharp.Editor.fsproj @@ -184,6 +184,7 @@ + diff --git a/FSharp.Editor.resx b/FSharp.Editor.resx index b84fec2d255..cc79f2dd7f9 100644 --- a/FSharp.Editor.resx +++ b/FSharp.Editor.resx @@ -243,4 +243,7 @@ Use subtraction instead of negation + + Use '<-' to mutate value + \ No newline at end of file diff --git a/xlf/FSharp.Editor.cs.xlf b/xlf/FSharp.Editor.cs.xlf index 21c7283d96f..8f4b72116da 100644 --- a/xlf/FSharp.Editor.cs.xlf +++ b/xlf/FSharp.Editor.cs.xlf @@ -192,6 +192,11 @@ Formátování + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.de.xlf b/xlf/FSharp.Editor.de.xlf index 53a83d33922..398d1dc6222 100644 --- a/xlf/FSharp.Editor.de.xlf +++ b/xlf/FSharp.Editor.de.xlf @@ -192,6 +192,11 @@ Formatierung + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.es.xlf b/xlf/FSharp.Editor.es.xlf index dc6c9c40f63..20d5f653715 100644 --- a/xlf/FSharp.Editor.es.xlf +++ b/xlf/FSharp.Editor.es.xlf @@ -192,6 +192,11 @@ Formato + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.fr.xlf b/xlf/FSharp.Editor.fr.xlf index 934e8d5c697..2c95c0d1292 100644 --- a/xlf/FSharp.Editor.fr.xlf +++ b/xlf/FSharp.Editor.fr.xlf @@ -192,6 +192,11 @@ Mise en forme + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.it.xlf b/xlf/FSharp.Editor.it.xlf index aee12fbb58f..1bb527a3361 100644 --- a/xlf/FSharp.Editor.it.xlf +++ b/xlf/FSharp.Editor.it.xlf @@ -192,6 +192,11 @@ Formattazione + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.ja.xlf b/xlf/FSharp.Editor.ja.xlf index 191ff6c3dfe..0a18d050f7f 100644 --- a/xlf/FSharp.Editor.ja.xlf +++ b/xlf/FSharp.Editor.ja.xlf @@ -192,6 +192,11 @@ 書式設定 + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.ko.xlf b/xlf/FSharp.Editor.ko.xlf index 60bb0063367..d95bde0d93e 100644 --- a/xlf/FSharp.Editor.ko.xlf +++ b/xlf/FSharp.Editor.ko.xlf @@ -192,6 +192,11 @@ 서식 + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.pl.xlf b/xlf/FSharp.Editor.pl.xlf index 152937264c9..579d328911a 100644 --- a/xlf/FSharp.Editor.pl.xlf +++ b/xlf/FSharp.Editor.pl.xlf @@ -192,6 +192,11 @@ Formatowanie + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.pt-BR.xlf b/xlf/FSharp.Editor.pt-BR.xlf index 3e18128e93f..ce039317f06 100644 --- a/xlf/FSharp.Editor.pt-BR.xlf +++ b/xlf/FSharp.Editor.pt-BR.xlf @@ -192,6 +192,11 @@ Formatação + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.ru.xlf b/xlf/FSharp.Editor.ru.xlf index db8fbd7b78f..72b8228c262 100644 --- a/xlf/FSharp.Editor.ru.xlf +++ b/xlf/FSharp.Editor.ru.xlf @@ -192,6 +192,11 @@ Форматирование + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.tr.xlf b/xlf/FSharp.Editor.tr.xlf index abf4e3c70e5..a8bd45e7577 100644 --- a/xlf/FSharp.Editor.tr.xlf +++ b/xlf/FSharp.Editor.tr.xlf @@ -192,6 +192,11 @@ Biçimlendirme + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.zh-Hans.xlf b/xlf/FSharp.Editor.zh-Hans.xlf index 0ef2dc2e91d..0ebd31d4d09 100644 --- a/xlf/FSharp.Editor.zh-Hans.xlf +++ b/xlf/FSharp.Editor.zh-Hans.xlf @@ -192,6 +192,11 @@ 正在格式化 + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast' diff --git a/xlf/FSharp.Editor.zh-Hant.xlf b/xlf/FSharp.Editor.zh-Hant.xlf index 254adcaa42a..da6ba8d19c3 100644 --- a/xlf/FSharp.Editor.zh-Hant.xlf +++ b/xlf/FSharp.Editor.zh-Hant.xlf @@ -192,6 +192,11 @@ 格式化 + + Use '<-' to mutate value + Use '<-' to mutate value + + Use 'upcast' Use 'upcast'