Skip to content

Commit

Permalink
Add MakeDeclarationMutable code fix (dotnet#10480)
Browse files Browse the repository at this point in the history
  • Loading branch information
cartermp authored and nosami committed Feb 22, 2021
1 parent 49e1b3a commit 4f618b7
Show file tree
Hide file tree
Showing 16 changed files with 142 additions and 0 deletions.
73 changes: 73 additions & 0 deletions CodeFix/MakeDeclarationMutable.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.Range
open FSharp.Compiler.SourceCodeServices
open FSharp.Compiler.AbstractIL.Internal.Library

[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "MakeDeclarationMutable"); Shared>]
type internal FSharpMakeDeclarationMutableFixProvider
[<ImportingConstructor>]
(
checkerProvider: FSharpCheckerProvider,
projectInfoManager: FSharpProjectOptionsManager
) =
inherit CodeFixProvider()

static let userOpName = "MakeDeclarationMutable"

let fixableDiagnosticIds = set ["FS0027"]

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! parseFileResults, _, 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 decl = checkFileResults.GetDeclarationLocation (fcsTextLineNumber, lexerSymbol.Ident.idRange.EndColumn, textLine.ToString(), lexerSymbol.FullIsland, false)

match decl with
// Only do this for symbols in the same file. That covers almost all cases anyways.
// We really shouldn't encourage making values mutable outside of local scopes anyways.
| FSharpFindDeclResult.DeclFound declRange when declRange.FileName = document.FilePath ->
let! span = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, declRange)

// Bail if it's a parameter, because like, that ain't allowed
do! Option.guard (not (parseFileResults.IsPositionContainedInACurriedParameter declRange.Start))

let title = SR.MakeDeclarationMutable()
let codeFix =
CodeFixHelpers.createTextChangeCodeFix(
title,
context,
(fun () -> asyncMaybe.Return [| TextChange(TextSpan(span.Start, 0), "mutable ") |]))

context.RegisterCodeFix(codeFix, diagnostics)
| _ ->
()
}
|> Async.Ignore
|> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
1 change: 1 addition & 0 deletions FSharp.Editor.fsproj
Expand Up @@ -184,6 +184,7 @@
<Compile Include="Commands\FsiCommandService.fs" />
<Compile Include="Commands\XmlDocCommandService.fs" />
<Compile Include="CodeFix\CodeFixHelpers.fs" />
<Compile Include="CodeFix\MakeDeclarationMutable.fs" />
<Compile Include="CodeFix\ChangeToUpcast.fs" />
<Compile Include="CodeFix\AddMissingEqualsToTypeDefinition.fs" />
<Compile Include="CodeFix\ConvertToSingleEqualsEqualityExpression.fs" />
Expand Down
3 changes: 3 additions & 0 deletions FSharp.Editor.resx
Expand Up @@ -219,6 +219,9 @@
<data name="FSharpDisposableTopLevelValuesClassificationType" xml:space="preserve">
<value>F# Dispostable Values (top-level)</value>
</data>
<data name="MakeDeclarationMutable" xml:space="preserve">
<value>Make declaration 'mutable'</value>
</data>
<data name="UseUpcastKeyword" xml:space="preserve">
<value>Use 'upcast'</value>
</data>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.cs.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Implementujte rozhraní bez anotace typu.</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">Před {0} vložte podtržítko.</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.de.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Schnittstelle ohne Typanmerkung implementieren</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">"{0}" einen Unterstrich voranstellen</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.es.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Implementar interfaz sin anotación de tipos</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">Colocar un carácter de subrayado delante de "{0}"</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.fr.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Implémenter l'interface sans annotation de type</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">Faire précéder '{0}' d'un trait de soulignement</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.it.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Implementa l'interfaccia senza annotazione di tipo</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">Anteponi a '{0}' un carattere di sottolineatura</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.ja.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">型の注釈を指定しないでインターフェイスを実装する</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">アンダースコアが含まれているプレフィックス '{0}'</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.ko.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">형식 주석 없이 인터페이스 구현</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">밑줄이 있는 '{0}' 접두사</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.pl.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Zaimplementuj interfejs bez adnotacji typu</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">Prefiks „{0}” ze znakiem podkreślenia</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.pt-BR.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Implementar a interface sem a anotação de tipo</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">Prefixo '{0}' sem sublinhado</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.ru.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Реализовать интерфейс без заметки с типом</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">Добавить символ подчеркивания как префикс "{0}"</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.tr.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Tür ek açıklaması olmadan arabirim uygulama</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">'{0}' öğesinin önüne alt çizgi ekleme</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.zh-Hans.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">无类型批注的实现接口</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">带下划线的前缀“{0}”</target>
Expand Down
5 changes: 5 additions & 0 deletions xlf/FSharp.Editor.zh-Hant.xlf
Expand Up @@ -52,6 +52,11 @@
<target state="translated">實作沒有類型註釋的介面</target>
<note />
</trans-unit>
<trans-unit id="MakeDeclarationMutable">
<source>Make declaration 'mutable'</source>
<target state="new">Make declaration 'mutable'</target>
<note />
</trans-unit>
<trans-unit id="PrefixValueNameWithUnderscore">
<source>Prefix '{0}' with underscore</source>
<target state="translated">有底線的前置詞 '{0}'</target>
Expand Down

0 comments on commit 4f618b7

Please sign in to comment.