Skip to content

Commit

Permalink
Added One Way of getting the changed Solution for ExplicitReturnTypes d…
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianAtWork committed Nov 13, 2023
1 parent 0e0718b commit 60233b5
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.CodeAnalysis.CodeRefactorings
open Microsoft.CodeAnalysis.CodeActions
open CancellableTasks
open System.Diagnostics

[<ExportCodeRefactoringProvider(FSharpConstants.FSharpLanguageName, Name = "AddExplicitReturnType"); Shared>]
type internal AddExplicitReturnType [<ImportingConstructor>] () =
Expand Down Expand Up @@ -48,10 +49,15 @@ type internal AddExplicitReturnType [<ImportingConstructor>] () =

let codeActionFunc = (fun (cancellationToken: CancellationToken) ->
task {
let oldDocument = context.Document

let! sourceText = context.Document.GetTextAsync(cancellationToken)
let changedText = getChangedText sourceText
context.Document.Project.Solution.Id
return context.Document.WithText(changedText)

let newDocument = context.Document.WithText(changedText)
let! changes = newDocument.GetTextChangesAsync(oldDocument)
Debugger.Log(0,"",$"{changes}")
return newDocument
}
)
let codeAction =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="CodeFixes\ConvertCSharpUsingToFSharpOpenTests.fs" />
<Compile Include="CodeFixes\ReplaceWithSuggestionTests.fs" />
<Compile Include="CodeFixes\RemoveUnnecessaryParenthesesTests.fs" />
<Compile Include="Refactors\RefactorTestFramework.fs" />
<Compile Include="Refactors\AddExplicitReturnType.fs" />
<Compile Include="Hints\HintTestFramework.fs" />
<Compile Include="Hints\OptionParserTests.fs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,47 +20,28 @@ open NUnit.Framework
open Microsoft.CodeAnalysis.CodeActions
open System.Collections.Generic
open Microsoft.VisualStudio.LanguageServices
open FSharp.Editor.Tests.Refactors.RefactorTestFramework
open Microsoft.Build.Utilities
open System.Threading


[<Fact>]
let ``Refactor changes something`` () =
task {

let ct = CancellationToken false

let code =
"""
let sum a b = a + b
"""

let! ct = Async.CancellationToken

let solution = RoslynTestHelpers.CreateSolution(code)
let workspace = solution.Workspace
let document = RoslynTestHelpers.GetSingleDocument solution

let spanStart = code.IndexOf "sum"
let span = TextSpan(spanStart, 3)


let refactorProvider = AddExplicitReturnType()
let refactoringActions= new List<CodeAction>()

let mutable refactorContext =
CodeRefactoringContext(document, span, (fun a -> refactoringActions.Add (a)), ct)

let! result = tryRefactor code spanStart ct (new AddExplicitReturnType())

do! refactorProvider.ComputeRefactoringsAsync refactorContext

let! operations = refactoringActions[0].GetOperationsAsync(ct)

for operation in operations do
operation.Apply (workspace,ct)



let! refactorText = refactorContext.TextDocument.GetTextAsync ct
refactorText
let! text = document.GetTextAsync ct
solution.Id
Assert.AreNotEqual(code,text.ToString(),"")
Assert.AreNotEqual(code,result.ToString(),"")

()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
module FSharp.Editor.Tests.Refactors.RefactorTestFramework


open System
open System.Collections.Immutable
open System.Collections.Generic
open System.Text.RegularExpressions

open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.CodeFixes
open Microsoft.CodeAnalysis.Text
open Microsoft.VisualStudio.FSharp.Editor
open Microsoft.VisualStudio.FSharp.Editor.CancellableTasks

open FSharp.Compiler.Diagnostics
open FSharp.Editor.Tests.Helpers
open Microsoft.CodeAnalysis.CodeRefactorings
open Microsoft.CodeAnalysis.CodeActions
open System.Collections.Generic
open System.Threading
open Microsoft.CodeAnalysis.Tags
open System.Reflection
open Microsoft.FSharp.Reflection

type DynamicHelper =
static member MkMethod<'t,'u> (mi:MethodInfo) o : 't -> 'u=
let typ = typeof<'t>
fun t ->
let args =
if (typ = typeof<unit>) then [||]
else
if not (FSharpType.IsTuple typ) then [| box t |]
else
FSharpValue.GetTupleFields t
mi.Invoke(o, args) :?> 'u

let (?) (o:'a) s : 'b =
let ty = o.GetType()
let field = ty.GetField(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic)
if field <> null then field.GetValue(o) :?> 'b
else
let prop = ty.GetProperty(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic)
if prop <> null then prop.GetValue(o, null) :?> 'b
else
let meth = ty.GetMethod(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic)
let d,r = FSharpType.GetFunctionElements(typeof<'b>)
typeof<DynamicHelper>.GetMethod("MkMethod").MakeGenericMethod([|d;r|]).Invoke(null, [| box meth; box o |]) :?> 'b
type TestCodeFix = { Message: string; FixedCode: string }

type Mode =
| Auto
| WithOption of CustomProjectOption: string
| WithSignature of FsiCode: string
| Manual of Squiggly: string * Diagnostic: string
| WithSettings of CodeFixesOptions

let inline toOption o =
match o with
| ValueSome v -> Some v
| _ -> None

let mockAction =
Action<CodeActions.CodeAction, ImmutableArray<Diagnostic>>(fun _ _ -> ())

let parseDiagnostic diagnostic =
let regex = Regex "([A-Z]+)(\d+)"
let matchGroups = regex.Match(diagnostic).Groups
let prefix = matchGroups[1].Value
let number = int matchGroups[2].Value
number, prefix

let getDocument code mode =
match mode with
| Auto -> RoslynTestHelpers.GetFsDocument code
| WithOption option -> RoslynTestHelpers.GetFsDocument(code, option)
| WithSignature fsiCode -> RoslynTestHelpers.GetFsiAndFsDocuments fsiCode code |> Seq.last
| Manual _ -> RoslynTestHelpers.GetFsDocument code
| WithSettings settings -> RoslynTestHelpers.GetFsDocument(code, customEditorOptions = settings)

let getRelevantDiagnostics (document: Document) =
cancellableTask {
let! _, checkFileResults = document.GetFSharpParseAndCheckResultsAsync "test"

return checkFileResults.Diagnostics
}
|> CancellableTask.startWithoutCancellation
|> fun task -> task.Result



let tryRefactor (code: string) (cursorPosition) (ct) (refactorProvider: 'T when 'T :> CodeRefactoringProvider ) =
cancellableTask {
let refactoringActions= new List<CodeAction>()

let mutable solution = RoslynTestHelpers.CreateSolution(code)

let document = RoslynTestHelpers.GetSingleDocument solution

use mutable workspace = solution.Workspace

let context = CodeRefactoringContext(document, TextSpan(cursorPosition,1), (fun a -> refactoringActions.Add a),ct)

do! refactorProvider.ComputeRefactoringsAsync context
for action in refactoringActions do
let! operations = action.GetOperationsAsync ct
for operation in operations do
let codeChangeOperation = operation :?> ApplyChangesOperation
codeChangeOperation.Apply(workspace,ct)
solution <- codeChangeOperation.ChangedSolution
()


let! changedText = solution.GetDocument(document.Id).GetTextAsync(ct)
return changedText
}
|> CancellableTask.startWithoutCancellation

0 comments on commit 60233b5

Please sign in to comment.