Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.

Commit 94c0d54

Browse files
cartermpnosami
authored andcommitted
Add UseMutationWhenValueIsMutable code fix (dotnet#10488)
1 parent 4f618b7 commit 94c0d54

16 files changed

+142
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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.Composition
6+
open System.Threading
7+
open System.Threading.Tasks
8+
9+
open Microsoft.CodeAnalysis.Text
10+
open Microsoft.CodeAnalysis.CodeFixes
11+
12+
open FSharp.Compiler.SourceCodeServices
13+
open FSharp.Compiler.Range
14+
15+
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "UseMutationWhenValueIsMutable"); Shared>]
16+
type internal FSharpUseMutationWhenValueIsMutableFixProvider
17+
[<ImportingConstructor>]
18+
(
19+
checkerProvider: FSharpCheckerProvider,
20+
projectInfoManager: FSharpProjectOptionsManager
21+
) =
22+
inherit CodeFixProvider()
23+
24+
static let userOpName = "UseMutationWhenValueIsMutable"
25+
26+
let fixableDiagnosticIds = set ["FS0020"]
27+
28+
override _.FixableDiagnosticIds = Seq.toImmutableArray fixableDiagnosticIds
29+
30+
override _.RegisterCodeFixesAsync context : Task =
31+
asyncMaybe {
32+
let diagnostics =
33+
context.Diagnostics
34+
|> Seq.filter (fun x -> fixableDiagnosticIds |> Set.contains x.Id)
35+
|> Seq.toImmutableArray
36+
37+
let document = context.Document
38+
do! Option.guard (not(isSignatureFile document.FilePath))
39+
let position = context.Span.Start
40+
let checker = checkerProvider.Checker
41+
let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, CancellationToken.None, userOpName)
42+
let! sourceText = document.GetTextAsync () |> liftTaskAsync
43+
let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions
44+
let textLine = sourceText.Lines.GetLineFromPosition position
45+
let textLinePos = sourceText.Lines.GetLinePosition position
46+
let fcsTextLineNumber = Line.fromZ textLinePos.Line
47+
let! _, _, checkFileResults = checker.ParseAndCheckDocument (document, projectOptions, sourceText=sourceText, userOpName=userOpName)
48+
let! lexerSymbol = Tokenizer.getSymbolAtPosition (document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false, false)
49+
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, lexerSymbol.Ident.idRange.EndColumn, textLine.ToString(), lexerSymbol.FullIsland)
50+
51+
match symbolUse.Symbol with
52+
| :? FSharpMemberOrFunctionOrValue as mfv when mfv.IsValue && mfv.IsMutable ->
53+
let title = SR.UseMutationWhenValueIsMutable()
54+
let! symbolSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate)
55+
let mutable pos = symbolSpan.End
56+
let mutable ch = sourceText.GetSubText(pos).ToString()
57+
58+
// We're looking for the possibly erroneous '='
59+
while pos <= context.Span.Length && ch <> "=" do
60+
pos <- pos + 1
61+
ch <- sourceText.GetSubText(pos).ToString()
62+
63+
let codeFix =
64+
CodeFixHelpers.createTextChangeCodeFix(
65+
title,
66+
context,
67+
(fun () -> asyncMaybe.Return [| TextChange(TextSpan(pos + 1, 1), "<-") |]))
68+
69+
context.RegisterCodeFix(codeFix, diagnostics)
70+
| _ -> ()
71+
}
72+
|> Async.Ignore
73+
|> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)

FSharp.Editor.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
<Compile Include="Commands\FsiCommandService.fs" />
185185
<Compile Include="Commands\XmlDocCommandService.fs" />
186186
<Compile Include="CodeFix\CodeFixHelpers.fs" />
187+
<Compile Include="CodeFix\UseMutationWhenValueIsMutable.fs" />
187188
<Compile Include="CodeFix\MakeDeclarationMutable.fs" />
188189
<Compile Include="CodeFix\ChangeToUpcast.fs" />
189190
<Compile Include="CodeFix\AddMissingEqualsToTypeDefinition.fs" />

FSharp.Editor.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,7 @@
243243
<data name="ChangePrefixNegationToInfixSubtraction" xml:space="preserve">
244244
<value>Use subtraction instead of negation</value>
245245
</data>
246+
<data name="UseMutationWhenValueIsMutable" xml:space="preserve">
247+
<value>Use '&lt;-' to mutate value</value>
248+
</data>
246249
</root>

xlf/FSharp.Editor.cs.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Formátování</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.de.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Formatierung</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.es.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Formato</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.fr.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Mise en forme</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.it.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Formattazione</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.ja.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">書式設定</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.ko.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">서식</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.pl.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Formatowanie</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.pt-BR.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Formatação</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.ru.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Форматирование</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.tr.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">Biçimlendirme</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.zh-Hans.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">正在格式化</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

xlf/FSharp.Editor.zh-Hant.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<target state="translated">格式化</target>
193193
<note />
194194
</trans-unit>
195+
<trans-unit id="UseMutationWhenValueIsMutable">
196+
<source>Use '&lt;-' to mutate value</source>
197+
<target state="new">Use '&lt;-' to mutate value</target>
198+
<note />
199+
</trans-unit>
195200
<trans-unit id="UseUpcastKeyword">
196201
<source>Use 'upcast'</source>
197202
<target state="new">Use 'upcast'</target>

0 commit comments

Comments
 (0)