Skip to content

Commit db68a6c

Browse files
authored
Fixing signature-related code fixes (dotnet#15766)
* Fixing signature-related code fixes * fixing merge issues * Removing unused code
1 parent fb01e0a commit db68a6c

File tree

8 files changed

+112
-78
lines changed

8 files changed

+112
-78
lines changed

Diff for: FSharp.Editor.sln

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.VS.FSI", "vsintegrat
1919
EndProject
2020
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Editor.IntegrationTests", "vsintegration\tests\FSharp.Editor.IntegrationTests\FSharp.Editor.IntegrationTests.csproj", "{42BE0F2F-BC45-437B-851D-E88A83201339}"
2121
EndProject
22+
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Test.Utilities", "tests\FSharp.Test.Utilities\FSharp.Test.Utilities.fsproj", "{B7148170-93C5-4F2F-B31D-85316D3248CF}"
23+
EndProject
2224
Global
2325
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2426
Debug|Any CPU = Debug|Any CPU
@@ -73,6 +75,12 @@ Global
7375
{42BE0F2F-BC45-437B-851D-E88A83201339}.Proto|Any CPU.Build.0 = Debug|Any CPU
7476
{42BE0F2F-BC45-437B-851D-E88A83201339}.Release|Any CPU.ActiveCfg = Release|Any CPU
7577
{42BE0F2F-BC45-437B-851D-E88A83201339}.Release|Any CPU.Build.0 = Release|Any CPU
78+
{B7148170-93C5-4F2F-B31D-85316D3248CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
79+
{B7148170-93C5-4F2F-B31D-85316D3248CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
80+
{B7148170-93C5-4F2F-B31D-85316D3248CF}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
81+
{B7148170-93C5-4F2F-B31D-85316D3248CF}.Proto|Any CPU.Build.0 = Debug|Any CPU
82+
{B7148170-93C5-4F2F-B31D-85316D3248CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
83+
{B7148170-93C5-4F2F-B31D-85316D3248CF}.Release|Any CPU.Build.0 = Release|Any CPU
7684
EndGlobalSection
7785
GlobalSection(SolutionProperties) = preSolution
7886
HideSolutionNode = FALSE

Diff for: tests/FSharp.Test.Utilities/ProjectGeneration.fs

+6-3
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ type SyntheticProject =
231231
OtherOptions: string list
232232
AutoAddModules: bool
233233
NugetReferences: Reference list
234-
FrameworkReferences: Reference list }
234+
FrameworkReferences: Reference list
235+
/// If set to true this project won't cause an exception if there are errors in the initial check
236+
SkipInitialCheck: bool }
235237

236238
static member Create(?name: string) =
237239
let name = defaultArg name $"TestProject_{Guid.NewGuid().ToString()[..7]}"
@@ -245,7 +247,8 @@ type SyntheticProject =
245247
OtherOptions = []
246248
AutoAddModules = true
247249
NugetReferences = []
248-
FrameworkReferences = [] }
250+
FrameworkReferences = []
251+
SkipInitialCheck = false }
249252

250253
static member Create([<ParamArray>] sourceFiles: SyntheticSourceFile[]) =
251254
{ SyntheticProject.Create() with SourceFiles = sourceFiles |> List.ofArray }
@@ -754,7 +757,7 @@ let SaveAndCheckProject project checker =
754757

755758
let! results = checker.ParseAndCheckProject(options)
756759

757-
if not (Array.isEmpty results.Diagnostics) then
760+
if not (Array.isEmpty results.Diagnostics || project.SkipInitialCheck) then
758761
failwith $"Project {project.Name} failed initial check: \n%A{results.Diagnostics}"
759762

760763
let! signatures =

Diff for: vsintegration/src/FSharp.Editor/CodeFixes/CodeFixHelpers.fs

-19
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ namespace Microsoft.VisualStudio.FSharp.Editor
44

55
open System
66
open System.Threading
7-
open System.Threading.Tasks
87
open System.Collections.Immutable
98
open System.Diagnostics
109

@@ -73,24 +72,6 @@ module internal CodeFixHelpers =
7372

7473
TelemetryReporter.ReportSingleEvent(TelemetryEvents.CodefixActivated, props)
7574

76-
let createFixAllProvider name getChanges =
77-
FixAllProvider.Create(fun fixAllCtx doc allDiagnostics ->
78-
backgroundTask {
79-
let sw = Stopwatch.StartNew()
80-
let! (changes: seq<TextChange>) = getChanges (doc, allDiagnostics, fixAllCtx.CancellationToken)
81-
let! text = doc.GetTextAsync(fixAllCtx.CancellationToken)
82-
let doc = doc.WithText(text.WithChanges(changes))
83-
84-
do
85-
reportCodeFixTelemetry
86-
allDiagnostics
87-
doc
88-
name
89-
[| "scope", fixAllCtx.Scope.ToString(); "elapsedMs", sw.ElapsedMilliseconds |]
90-
91-
return doc
92-
})
93-
9475
let createTextChangeCodeFix (name: string, title: string, context: CodeFixContext, changes: TextChange seq) =
9576
CodeAction.Create(
9677
title,

Diff for: vsintegration/src/FSharp.Editor/CodeFixes/RenameParamToMatchSignature.fs

+34-46
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
namespace Microsoft.VisualStudio.FSharp.Editor
44

55
open System.Composition
6-
open System.Threading
7-
open System.Threading.Tasks
86
open System.Collections.Immutable
97
open System.Text.RegularExpressions
108

@@ -13,11 +11,13 @@ open Microsoft.CodeAnalysis.Text
1311
open Microsoft.CodeAnalysis.CodeFixes
1412
open Microsoft.VisualStudio.FSharp.Editor.SymbolHelpers
1513

14+
open FSharp.Compiler.Diagnostics
1615
open FSharp.Compiler.Tokenization.FSharpKeywords
1716

17+
open CancellableTasks
18+
1819
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = CodeFix.FSharpRenameParamToMatchSignature); Shared>]
1920
type internal RenameParamToMatchSignatureCodeFixProvider [<ImportingConstructor>] () =
20-
2121
inherit CodeFixProvider()
2222

2323
let getSuggestion (d: Diagnostic) =
@@ -28,53 +28,41 @@ type internal RenameParamToMatchSignatureCodeFixProvider [<ImportingConstructor>
2828
else
2929
ValueNone
3030

31-
override _.FixableDiagnosticIds = ImmutableArray.Create("FS3218")
31+
override _.FixableDiagnosticIds = ImmutableArray.Create "FS3218"
32+
33+
override this.RegisterCodeFixesAsync context = context.RegisterFsharpFix this
3234

33-
member this.GetChanges(document: Document, diagnostics: ImmutableArray<Diagnostic>, ct: CancellationToken) =
34-
backgroundTask {
35-
let! sourceText = document.GetTextAsync(ct)
35+
override this.GetFixAllProvider() = this.RegisterFsharpFixAll()
3636

37-
let! changes =
38-
seq {
39-
for d in diagnostics do
40-
let suggestionOpt = getSuggestion d
37+
interface IFSharpCodeFixProvider with
38+
member _.GetCodeFixIfAppliesAsync context =
39+
cancellableTask {
40+
let! sourceText = context.GetSourceTextAsync()
4141

42-
match suggestionOpt with
43-
| ValueSome suggestion ->
44-
let replacement = NormalizeIdentifierBackticks suggestion
42+
let suggestionOpt = getSuggestion context.Diagnostics[0]
4543

46-
async {
47-
let! symbolUses = getSymbolUsesOfSymbolAtLocationInDocument (document, d.Location.SourceSpan.Start)
48-
let symbolUses = symbolUses |> Option.defaultValue [||]
44+
match suggestionOpt with
45+
| ValueSome suggestion ->
46+
let replacement = NormalizeIdentifierBackticks suggestion
4947

50-
return
51-
[|
52-
for symbolUse in symbolUses do
53-
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.Range) with
54-
| None -> ()
55-
| Some span ->
56-
let textSpan = Tokenizer.fixupSpan (sourceText, span)
57-
yield TextChange(textSpan, replacement)
58-
|]
48+
let! symbolUses = getSymbolUsesOfSymbolAtLocationInDocument (context.Document, context.Span.Start)
49+
let symbolUses = symbolUses |> Option.defaultValue [||]
5950

51+
let changes =
52+
[
53+
for symbolUse in symbolUses do
54+
let span = RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.Range)
55+
let textSpan = Tokenizer.fixupSpan (sourceText, span)
56+
yield TextChange(textSpan, replacement)
57+
]
58+
59+
return
60+
ValueSome
61+
{
62+
Name = CodeFix.FSharpRenameParamToMatchSignature
63+
Message = CompilerDiagnostics.GetErrorMessage(FSharpDiagnosticKind.ReplaceWithSuggestion suggestion)
64+
Changes = changes
6065
}
61-
| ValueNone -> ()
62-
}
63-
|> Async.Parallel
64-
65-
return (changes |> Seq.concat)
66-
}
67-
68-
override this.RegisterCodeFixesAsync ctx : Task =
69-
backgroundTask {
70-
let title = ctx.Diagnostics |> Seq.head |> getSuggestion
71-
72-
match title with
73-
| ValueSome title ->
74-
let! changes = this.GetChanges(ctx.Document, ctx.Diagnostics, ctx.CancellationToken)
75-
ctx.RegisterFsharpFix(CodeFix.FSharpRenameParamToMatchSignature, title, changes)
76-
| ValueNone -> ()
77-
}
78-
79-
override this.GetFixAllProvider() =
80-
CodeFixHelpers.createFixAllProvider CodeFix.FSharpRenameParamToMatchSignature this.GetChanges
66+
67+
| ValueNone -> return ValueNone
68+
}

Diff for: vsintegration/tests/FSharp.Editor.Tests/CodeFixes/CodeFixTestFramework.fs

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type TestCodeFix = { Message: string; FixedCode: string }
2020
type Mode =
2121
| Auto
2222
| WithOption of CustomProjectOption: string
23+
| WithSignature of FsiCode: string
2324
| Manual of Squiggly: string * Diagnostic: string
2425

2526
let inline toOption o =
@@ -41,6 +42,7 @@ let getDocument code mode =
4142
match mode with
4243
| Auto -> RoslynTestHelpers.GetFsDocument code
4344
| WithOption option -> RoslynTestHelpers.GetFsDocument(code, option)
45+
| WithSignature fsiCode -> RoslynTestHelpers.GetFsiAndFsDocuments fsiCode code |> Seq.last
4446
| Manual _ -> RoslynTestHelpers.GetFsDocument code
4547

4648
let getRelevantDiagnostics (document: Document) =
@@ -64,6 +66,7 @@ let createTestCodeFixContext (code: string) document (mode: Mode) diagnosticIds
6466
getRelevantDiagnostics document
6567
|> Array.filter (fun d -> diagnosticIds |> Seq.contains d.ErrorNumberText)
6668
| WithOption _ -> getRelevantDiagnostics document
69+
| WithSignature _ -> getRelevantDiagnostics document
6770
| Manual (squiggly, diagnostic) ->
6871
let spanStart = code.IndexOf squiggly
6972
let span = TextSpan(spanStart, squiggly.Length)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
module FSharp.Editor.Tests.CodeFixes.RenameParamToMatchSignatureTests
4+
5+
open Microsoft.VisualStudio.FSharp.Editor
6+
open Xunit
7+
8+
open CodeFixTestFramework
9+
10+
let private codeFix = RenameParamToMatchSignatureCodeFixProvider()
11+
12+
[<Fact>]
13+
let ``Fixes FS3218`` () =
14+
let fsCode =
15+
"""
16+
module Library
17+
18+
let id y = y
19+
"""
20+
21+
let fsiCode =
22+
"""
23+
module Library
24+
25+
val id: x: 'a -> 'a
26+
"""
27+
28+
let expected =
29+
Some
30+
{
31+
Message = "Replace with 'x'"
32+
FixedCode =
33+
"""
34+
module Library
35+
36+
let id x = x
37+
"""
38+
}
39+
40+
let actual = codeFix |> tryFix fsCode (WithSignature fsiCode)
41+
42+
Assert.Equal(expected, actual)

Diff for: vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
<Compile Include="CodeFixes\ChangeEqualsInFieldTypeToColonTests.fs" />
5959
<Compile Include="CodeFixes\RemoveUnusedOpensTests.fs" />
6060
<Compile Include="CodeFixes\SimplifyNameTests.fs" />
61+
<Compile Include="CodeFixes\RenameParamToMatchSignatureTests.fs" />
6162
<Compile Include="Hints\HintTestFramework.fs" />
6263
<Compile Include="Hints\OptionParserTests.fs" />
6364
<Compile Include="Hints\InlineParameterNameHintTests.fs" />

Diff for: vsintegration/tests/FSharp.Editor.Tests/Helpers/RoslynHelpers.fs

+18-10
Original file line numberDiff line numberDiff line change
@@ -358,17 +358,25 @@ type RoslynTestHelpers private () =
358358
|> RoslynTestHelpers.GetSingleDocument
359359

360360
static member GetFsiAndFsDocuments (fsiCode: string) (fsCode: string) =
361-
let projectId = ProjectId.CreateNewId()
362-
let projFilePath = "C:\\test.fsproj"
363-
364-
let fsiDocInfo =
365-
RoslynTestHelpers.CreateDocumentInfo projectId "C:\\test.fsi" fsiCode
366-
367-
let fsDocInfo = RoslynTestHelpers.CreateDocumentInfo projectId "C:\\test.fs" fsCode
368-
369361
let projInfo =
370-
RoslynTestHelpers.CreateProjectInfo projectId projFilePath [ fsiDocInfo; fsDocInfo ]
362+
{ SyntheticProject.Create(
363+
{ sourceFile "test" [] with
364+
SignatureFile = Custom fsiCode
365+
Source = fsCode
366+
}
367+
) with
368+
369+
AutoAddModules = false
370+
SkipInitialCheck = true
371+
OtherOptions =
372+
[
373+
"--targetprofile:netcore" // without this lib some symbols are not loaded
374+
"--nowarn:3384" // The .NET SDK for this script could not be determined
375+
]
376+
}
371377

372-
let solution = RoslynTestHelpers.CreateSolution [ projInfo ]
378+
let solution, _ = RoslynTestHelpers.CreateSolution projInfo
373379
let project = solution.Projects |> Seq.exactlyOne
380+
374381
project.Documents
382+
|> Seq.sortWith (fun d1 _ -> if d1.IsFSharpSignatureFile then -1 else 1)

0 commit comments

Comments
 (0)