@@ -4,8 +4,6 @@ namespace Microsoft.VisualStudio.FSharp.Editor
4
4
5
5
open System
6
6
open System.Composition
7
- open System.Threading .Tasks
8
- open System.Threading
9
7
open System.Collections .Immutable
10
8
11
9
open Microsoft.CodeAnalysis .Text
@@ -14,6 +12,7 @@ open Microsoft.CodeAnalysis.CodeFixes
14
12
open FSharp.Compiler .EditorServices
15
13
open FSharp.Compiler .Text
16
14
open FSharp.Compiler .Symbols
15
+
17
16
open CancellableTasks
18
17
19
18
[<ExportCodeFixProvider( FSharpConstants.FSharpLanguageName, Name = CodeFix.AddTypeAnnotationToObjectOfIndeterminateType); Shared>]
@@ -24,88 +23,98 @@ type internal AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider [<Importin
24
23
25
24
override _.FixableDiagnosticIds = ImmutableArray.Create( " FS0072" , " FS3245" )
26
25
27
- override _.RegisterCodeFixesAsync context : Task =
28
- asyncMaybe {
29
-
30
- let document = context.Document
31
- let position = context.Span.Start
32
-
33
- let! sourceText = document.GetTextAsync( context.CancellationToken)
34
- let textLine = sourceText.Lines.GetLineFromPosition position
35
- let textLinePos = sourceText.Lines.GetLinePosition position
36
- let fcsTextLineNumber = Line.fromZ textLinePos.Line
37
-
38
- let! lexerSymbol =
39
- document.TryFindFSharpLexerSymbolAsync(
40
- position,
41
- SymbolLookupKind.Greedy,
42
- false ,
43
- false ,
44
- nameof ( AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider)
45
- )
46
-
47
- let! _ , checkFileResults =
48
- document.GetFSharpParseAndCheckResultsAsync( nameof ( AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider))
49
- |> CancellableTask.start context.CancellationToken
50
- |> Async.AwaitTask
51
- |> liftAsync
52
-
53
- let decl =
54
- checkFileResults.GetDeclarationLocation(
55
- fcsTextLineNumber,
56
- lexerSymbol.Ident.idRange.EndColumn,
57
- textLine.ToString(),
58
- lexerSymbol.FullIsland,
59
- false
60
- )
61
-
62
- match decl with
63
- | FindDeclResult.DeclFound declRange when declRange.FileName = document.FilePath ->
64
- let! declSpan = RoslynHelpers.TryFSharpRangeToTextSpan( sourceText, declRange)
65
- let declTextLine = sourceText.Lines.GetLineFromPosition declSpan.Start
66
-
67
- let! symbolUse =
68
- checkFileResults.GetSymbolUseAtLocation(
69
- declRange.StartLine,
70
- declRange.EndColumn,
71
- declTextLine.ToString(),
72
- lexerSymbol.FullIsland
26
+ override this.RegisterCodeFixesAsync context = context.RegisterFsharpFix this
27
+
28
+ interface IFSharpCodeFixProvider with
29
+ member _.GetCodeFixIfAppliesAsync context =
30
+ cancellableTask {
31
+ let document = context.Document
32
+ let position = context.Span.Start
33
+
34
+ let! lexerSymbolOpt =
35
+ document.TryFindFSharpLexerSymbolAsync(
36
+ position,
37
+ SymbolLookupKind.Greedy,
38
+ false ,
39
+ false ,
40
+ nameof AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider
73
41
)
74
42
75
- match symbolUse.Symbol with
76
- | : ? FSharpMemberOrFunctionOrValue as mfv ->
77
- let typeString = mfv.FullType.FormatWithConstraints symbolUse.DisplayContext
78
-
79
- let alreadyWrappedInParens =
80
- let rec leftLoop ch pos =
81
- if not ( Char.IsWhiteSpace( ch)) then
82
- ch = '('
83
- else
84
- leftLoop sourceText.[ pos - 1 ] ( pos - 1 )
85
-
86
- let rec rightLoop ch pos =
87
- if not ( Char.IsWhiteSpace( ch)) then
88
- ch = ')'
89
- else
90
- rightLoop sourceText.[ pos + 1 ] ( pos + 1 )
91
-
92
- let hasLeftParen = leftLoop sourceText.[ declSpan.Start - 1 ] ( declSpan.Start - 1 )
93
- let hasRightParen = rightLoop sourceText.[ declSpan.End] declSpan.End
94
- hasLeftParen && hasRightParen
95
-
96
- let changes =
97
- [
98
- if alreadyWrappedInParens then
99
- TextChange( TextSpan( declSpan.End, 0 ), " : " + typeString)
100
- else
101
- TextChange( TextSpan( declSpan.Start, 0 ), " (" )
102
- TextChange( TextSpan( declSpan.End + 1 , 0 ), " : " + typeString + " )" )
103
- ]
104
-
105
- context.RegisterFsharpFix( CodeFix.AddTypeAnnotationToObjectOfIndeterminateType, title, changes)
106
-
107
- | _ -> ()
108
- | _ -> ()
109
- }
110
- |> Async.Ignore
111
- |> RoslynHelpers.StartAsyncUnitAsTask( context.CancellationToken)
43
+ match lexerSymbolOpt with
44
+ | None -> return ValueNone
45
+ | Some lexerSymbol ->
46
+ let! sourceText = context.GetSourceTextAsync()
47
+ let textLine = sourceText.Lines.GetLineFromPosition position
48
+ let textLinePos = sourceText.Lines.GetLinePosition position
49
+ let fcsTextLineNumber = Line.fromZ textLinePos.Line
50
+
51
+ let! _ , checkFileResults =
52
+ document.GetFSharpParseAndCheckResultsAsync( nameof AddTypeAnnotationToObjectOfIndeterminateTypeFixProvider)
53
+
54
+ let decl =
55
+ checkFileResults.GetDeclarationLocation(
56
+ fcsTextLineNumber,
57
+ lexerSymbol.Ident.idRange.EndColumn,
58
+ textLine.ToString(),
59
+ lexerSymbol.FullIsland,
60
+ false
61
+ )
62
+
63
+ match decl with
64
+ | FindDeclResult.DeclFound declRange when declRange.FileName = document.FilePath ->
65
+ let declSpan = RoslynHelpers.FSharpRangeToTextSpan( sourceText, declRange)
66
+ let declTextLine = sourceText.Lines.GetLineFromPosition declSpan.Start
67
+
68
+ let symbolUseOpt =
69
+ checkFileResults.GetSymbolUseAtLocation(
70
+ declRange.StartLine,
71
+ declRange.EndColumn,
72
+ declTextLine.ToString(),
73
+ lexerSymbol.FullIsland
74
+ )
75
+
76
+ match symbolUseOpt with
77
+ | None -> return ValueNone
78
+ | Some symbolUse ->
79
+ match symbolUse.Symbol with
80
+ | : ? FSharpMemberOrFunctionOrValue as mfv when not mfv .FullType .IsGenericParameter ->
81
+ let typeString = mfv.FullType.FormatWithConstraints symbolUse.DisplayContext
82
+
83
+ let alreadyWrappedInParens =
84
+ let rec leftLoop ch pos =
85
+ if not ( Char.IsWhiteSpace( ch)) then
86
+ ch = '('
87
+ else
88
+ leftLoop sourceText[ pos - 1 ] ( pos - 1 )
89
+
90
+ let rec rightLoop ch pos =
91
+ if not ( Char.IsWhiteSpace( ch)) then
92
+ ch = ')'
93
+ else
94
+ rightLoop sourceText[ pos + 1 ] ( pos + 1 )
95
+
96
+ let hasLeftParen = leftLoop sourceText[ declSpan.Start - 1 ] ( declSpan.Start - 1 )
97
+ let hasRightParen = rightLoop sourceText[ declSpan.End] declSpan.End
98
+ hasLeftParen && hasRightParen
99
+
100
+ let changes =
101
+ [
102
+ if alreadyWrappedInParens then
103
+ TextChange( TextSpan( declSpan.End, 0 ), " : " + typeString)
104
+ else
105
+ TextChange( TextSpan( declSpan.Start, 0 ), " (" )
106
+ TextChange( TextSpan( declSpan.End, 0 ), " : " + typeString + " )" )
107
+ ]
108
+
109
+ return
110
+ ValueSome
111
+ {
112
+ Name = CodeFix.AddTypeAnnotationToObjectOfIndeterminateType
113
+ Message = title
114
+ Changes = changes
115
+ }
116
+
117
+ | _ -> return ValueNone
118
+
119
+ | _ -> return ValueNone
120
+ }
0 commit comments