1
- module FSharpLanguageServer.Conversions
1
+ module FSharpLanguageServer.Conversions
2
2
3
3
open LSP.Log
4
4
open FSharp.Compiler
@@ -8,45 +8,44 @@ open System.IO
8
8
open LSP.Types
9
9
open FSharp.Data
10
10
11
- module Ast = FSharp.Compiler.Ast
12
-
13
11
/// Convert an F# Compiler Services 'FSharpErrorInfo' to an LSP 'Range'
14
- let private errorAsRange ( err : FSharpErrorInfo ): Range =
12
+ let private errorAsRange ( err : FSharpDiagnostic ): Range =
15
13
{
16
14
// Got error "The field, constructor or member 'StartLine' is not defined"
17
15
start = { line= err.StartLineAlternate-1 ; character= err.StartColumn}
18
16
`` end `` = { line= err.EndLineAlternate-1 ; character= err.EndColumn}
19
17
}
20
18
21
19
/// Convert an F# `Range.pos` to an LSP `Position`
22
- let private asPosition ( p : Range .pos): Position =
20
+ let private asPosition ( p : Text .pos): Position =
23
21
{
24
22
line= p.Line-1
25
23
character= p.Column
26
24
}
27
25
28
26
/// Convert an F# `Range.range` to an LSP `Range`
29
- let asRange ( r : Range .range): Range =
27
+ let asRange ( r : Text .range): Range =
30
28
{
31
29
start= asPosition r.Start
32
30
`` end `` = asPosition r.End
33
31
}
34
32
35
33
/// Convert an F# `Range.range` to an LSP `Location`
36
- let private asLocation ( l : Range .range): Location =
37
- {
34
+ let private asLocation ( l : Text .range): Location =
35
+ {
38
36
uri= Uri( " file://" + l.FileName)
39
- range = asRange l
37
+ range = asRange l
40
38
}
41
39
42
40
/// Convert an F# Compiler Services 'FSharpErrorSeverity' to an LSP 'DiagnosticSeverity'
43
- let private asDiagnosticSeverity ( s : FSharpErrorSeverity ): DiagnosticSeverity =
44
- match s with
45
- | FSharpErrorSeverity.Warning -> DiagnosticSeverity.Warning
46
- | FSharpErrorSeverity.Error -> DiagnosticSeverity.Error
41
+ let private asDiagnosticSeverity ( s : FSharpDiagnosticSeverity ): DiagnosticSeverity =
42
+ match s with
43
+ | FSharpDiagnosticSeverity.Warning -> DiagnosticSeverity.Warning
44
+ | FSharpDiagnosticSeverity.Error -> DiagnosticSeverity.Error
45
+ | FSharpDiagnosticSeverity.Info -> DiagnosticSeverity.Information
47
46
48
47
/// Convert an F# Compiler Services 'FSharpErrorInfo' to an LSP 'Diagnostic'
49
- let asDiagnostic ( err : FSharpErrorInfo ): Diagnostic =
48
+ let asDiagnostic ( err : FSharpDiagnostic ): Diagnostic =
50
49
{
51
50
range = errorAsRange( err)
52
51
severity = Some( asDiagnosticSeverity( err.Severity))
@@ -56,18 +55,18 @@ let asDiagnostic(err: FSharpErrorInfo): Diagnostic =
56
55
}
57
56
58
57
/// Create a Diagnostic
59
- let diagnostic ( message : string , range : Range .range, severity : DiagnosticSeverity ): Diagnostic =
58
+ let diagnostic ( message : string , range : Text .range, severity : DiagnosticSeverity ): Diagnostic =
60
59
{
61
60
range = asRange( range)
62
61
severity = Some( severity)
63
- code = None
64
- source = None
62
+ code = None
63
+ source = None
65
64
message = message
66
65
}
67
-
66
+
68
67
/// Some compiler errors have no location in the file and should be displayed at the top of the file
69
- let private hasNoLocation ( err : FSharpErrorInfo ): bool =
70
- err.StartLineAlternate-1 = 0 &&
68
+ let private hasNoLocation ( err : FSharpDiagnostic ): bool =
69
+ err.StartLineAlternate-1 = 0 &&
71
70
err.StartColumn = 0 &&
72
71
err.EndLineAlternate-1 = 0 &&
73
72
err.EndColumn = 0
@@ -76,60 +75,60 @@ let private hasNoLocation(err: FSharpErrorInfo): bool =
76
75
let errorAtTop ( message : string ): Diagnostic =
77
76
{
78
77
range = { start = { line= 0 ; character= 0 }; `` end `` = { line= 0 ; character= 1 } }
79
- severity = Some( DiagnosticSeverity.Error)
78
+ severity = Some( DiagnosticSeverity.Error)
80
79
code = None
81
- source = None
80
+ source = None
82
81
message = message
83
82
}
84
83
85
84
/// Convert a list of F# Compiler Services 'FSharpErrorInfo' to LSP 'Diagnostic'
86
- let asDiagnostics ( errors : FSharpErrorInfo seq): Diagnostic list =
87
- [
88
- for err in errors do
89
- if hasNoLocation( err) then
85
+ let asDiagnostics ( errors : FSharpDiagnostic seq): Diagnostic list =
86
+ [
87
+ for err in errors do
88
+ if hasNoLocation( err) then
90
89
yield errorAtTop( sprintf " %s : %s " err.Subcategory err.Message)
91
90
else
92
- yield asDiagnostic( err)
91
+ yield asDiagnostic( err)
93
92
]
94
93
95
94
96
95
/// Convert an F# `FSharpToolTipElement` to an LSP `Hover`
97
- let asHover ( FSharpToolTipText tips ): Hover =
98
- let elements =
96
+ let asHover ( FSharpToolTipText tips ): Hover =
97
+ let elements =
99
98
[ for t in tips do
100
- match t with
99
+ match t with
101
100
| FSharpToolTipElement.CompositionError( e) -> dprintfn " Error rendering tooltip: %s " e
102
- | FSharpToolTipElement.None -> ()
103
- | FSharpToolTipElement.Group( elements) ->
101
+ | FSharpToolTipElement.None -> ()
102
+ | FSharpToolTipElement.Group( elements) ->
104
103
yield ! elements ]
105
- let contents =
106
- match elements with
104
+ let contents =
105
+ match elements with
107
106
| [] -> []
108
- | [ one] ->
109
- [ yield HighlightedString( one.MainDescription, " fsharp" )
110
- match TipFormatter.docComment( one.XmlDoc) with
107
+ | [ one] ->
108
+ [ yield HighlightedString( one.MainDescription, " fsharp" )
109
+ match TipFormatter.docComment( one.XmlDoc) with
111
110
| None -> ()
112
111
| Some( markdown) -> yield PlainString( markdown + " \n\n " )
113
- match one.Remarks with
114
- | None | Some( " " ) -> ()
115
- | Some( remarks) ->
112
+ match one.Remarks with
113
+ | None | Some( " " ) -> ()
114
+ | Some( remarks) ->
116
115
yield PlainString( " *" + remarks + " *\n\n " ) ]
117
- | many ->
116
+ | many ->
118
117
let last = List.last( many)
119
- [ for e in many do
118
+ [ for e in many do
120
119
yield HighlightedString( e.MainDescription, " fsharp" )
121
- match TipFormatter.docSummaryOnly( last.XmlDoc) with
120
+ match TipFormatter.docSummaryOnly( last.XmlDoc) with
122
121
| None -> ()
123
122
| Some( markdown) -> yield PlainString( markdown)
124
- match last.Remarks with
125
- | None | Some( " " ) -> ()
126
- | Some( remarks) ->
123
+ match last.Remarks with
124
+ | None | Some( " " ) -> ()
125
+ | Some( remarks) ->
127
126
yield PlainString( " *" + remarks + " *\n\n " ) ]
128
127
{ contents= contents; range= None}
129
128
130
129
/// Convert an F# `FSharpGlyph` to an LSP `CompletionItemKind`
131
- let private asCompletionItemKind ( k : FSharpGlyph ): CompletionItemKind =
132
- match k with
130
+ let private asCompletionItemKind ( k : FSharpGlyph ): CompletionItemKind =
131
+ match k with
133
132
| FSharpGlyph.Class -> CompletionItemKind.Class
134
133
| FSharpGlyph.Constant -> CompletionItemKind.Constant
135
134
| FSharpGlyph.Delegate -> CompletionItemKind.Property // ?
@@ -153,9 +152,9 @@ let private asCompletionItemKind(k: FSharpGlyph): CompletionItemKind =
153
152
| FSharpGlyph.Error -> CompletionItemKind.Class // ?
154
153
155
154
/// Convert an F# `FSharpDeclarationListItem` to an LSP `CompletionItem`
156
- let private asCompletionItem ( i : FSharpDeclarationListItem ): CompletionItem =
157
- { defaultCompletionItem with
158
- label = i.Name
155
+ let private asCompletionItem ( i : FSharpDeclarationListItem ): CompletionItem =
156
+ { defaultCompletionItem with
157
+ label = i.Name
159
158
insertText = Some( i.NameInCode)
160
159
kind = Some( asCompletionItemKind( i.Glyph))
161
160
detail = Some( i.FullName)
@@ -165,50 +164,50 @@ let private asCompletionItem(i: FSharpDeclarationListItem): CompletionItem =
165
164
166
165
/// Convert an F# `FSharpDeclarationListInfo` to an LSP `CompletionList`
167
166
/// Used in rendering autocomplete lists
168
- let asCompletionList ( ds : FSharpDeclarationListInfo ): CompletionList =
167
+ let asCompletionList ( ds : FSharpDeclarationListInfo ): CompletionList =
169
168
let items = [ for i in ds.Items do yield asCompletionItem( i)]
170
169
{ isIncomplete= List.isEmpty( items); items= items}
171
170
172
171
/// Convert an F# `FSharpMethodGroupItemParameter` to an LSP `ParameterInformation`
173
- let private asParameterInformation ( p : FSharpMethodGroupItemParameter ): ParameterInformation =
172
+ let private asParameterInformation ( p : FSharpMethodGroupItemParameter ): ParameterInformation =
174
173
{
175
174
label = p.ParameterName
176
175
documentation = Some p.Display
177
176
}
178
177
179
178
/// Convert an F# method name + `FSharpMethodGroupItem` to an LSP `SignatureInformation`
180
179
/// Used in providing signature help after autocompleting
181
- let asSignatureInformation ( methodName : string , s : FSharpMethodGroupItem ): SignatureInformation =
182
- let doc = match s.Description with
183
- | FSharpToolTipText [ FSharpToolTipElement.Group [ tip]] -> Some tip.MainDescription
184
- | _ ->
185
- dprintfn " Can't render documentation %A " s.Description
186
- None
180
+ let asSignatureInformation ( methodName : string , s : FSharpMethodGroupItem ): SignatureInformation =
181
+ let doc = match s.Description with
182
+ | FSharpToolTipText [ FSharpToolTipElement.Group [ tip]] -> Some tip.MainDescription
183
+ | _ ->
184
+ dprintfn " Can't render documentation %A " s.Description
185
+ None
187
186
let parameterName ( p : FSharpMethodGroupItemParameter ) = p.ParameterName
188
187
let parameterNames = Array.map parameterName s.Parameters
189
188
{
190
- label = sprintf " %s (%s )" methodName ( String.concat " , " parameterNames)
191
- documentation = doc
189
+ label = sprintf " %s (%s )" methodName ( String.concat " , " parameterNames)
190
+ documentation = doc
192
191
parameters = Array.map asParameterInformation s.Parameters |> List.ofArray
193
192
}
194
193
195
194
/// Get the lcation where `s` was declared
196
- let declarationLocation ( s : FSharpSymbol ): Location option =
197
- match s.DeclarationLocation with
198
- | None ->
199
- dprintfn " Symbol %s has no declaration" s.FullName
200
- None
195
+ let declarationLocation ( s : FSharpSymbol ): Location option =
196
+ match s.DeclarationLocation with
197
+ | None ->
198
+ dprintfn " Symbol %s has no declaration" s.FullName
199
+ None
201
200
| Some l ->
202
201
Some( asLocation( l))
203
202
204
203
/// Get the location where `s` was used
205
- let useLocation ( s : FSharpSymbolUse ): Location =
204
+ let useLocation ( s : FSharpSymbolUse ): Location =
206
205
asLocation( s.RangeAlternate)
207
206
208
207
/// Convert an F# `FSharpNavigationDeclarationItemKind` to an LSP `SymbolKind`
209
208
/// `FSharpNavigationDeclarationItemKind` is the level of symbol-type information you get when parsing without typechecking
210
- let private asSymbolKind ( k : FSharpNavigationDeclarationItemKind ): SymbolKind =
211
- match k with
209
+ let private asSymbolKind ( k : FSharpNavigationDeclarationItemKind ): SymbolKind =
210
+ match k with
212
211
| NamespaceDecl -> SymbolKind.Namespace
213
212
| ModuleFileDecl -> SymbolKind.Module
214
213
| ExnDecl -> SymbolKind.Class
@@ -222,17 +221,17 @@ let private asSymbolKind(k: FSharpNavigationDeclarationItemKind): SymbolKind =
222
221
/// Convert an F# `NavigationDeclarationItem` to an LSP `SymbolInformation`
223
222
/// `NavigationDeclarationItem` is the parsed AST representation of a symbol without typechecking
224
223
/// `container` is present when `d` is part of a module or type
225
- let asSymbolInformation ( d : NavigationDeclarationItem , container : NavigationDeclarationItem option): SymbolInformation =
226
- let declarationName ( d : NavigationDeclarationItem ) = d.Name
224
+ let asSymbolInformation ( d : NavigationItem , container : NavigationItem option): SymbolInformation =
225
+ let declarationName ( d : NavigationItem ) = d.Name
227
226
{
228
- name= d.Name
229
- kind= asSymbolKind d.Kind
230
- location= asLocation d.Range
227
+ name= d.Name
228
+ kind= asSymbolKind d.Kind
229
+ location= asLocation d.Range
231
230
containerName= Option.map declarationName container
232
231
}
233
232
234
233
/// Convert symbols declared in an .fsi file to a CodeLens that helps the user navigate to the definition
235
- let asGoToImplementation ( name : string list , file : FileInfo , range : Range .range): CodeLens =
234
+ let asGoToImplementation ( name : string list , file : FileInfo , range : Text .range): CodeLens =
236
235
let jsonFile = JsonValue.String( file.FullName)
237
236
let jsonName = JsonValue.Array([| for i in name do yield JsonValue.String( i)|])
238
237
{
@@ -241,13 +240,13 @@ let asGoToImplementation(name: string list, file: FileInfo, range: Range.range):
241
240
data= JsonValue.Array([| jsonFile; jsonName|])
242
241
}
243
242
244
- let goToImplementationData ( goTo : CodeLens ) =
245
- match goTo.data with
246
- | JsonValue.Array([| JsonValue.String( file); JsonValue.Array( jsonNames)|]) ->
243
+ let goToImplementationData ( goTo : CodeLens ) =
244
+ match goTo.data with
245
+ | JsonValue.Array([| JsonValue.String( file); JsonValue.Array( jsonNames)|]) ->
247
246
FileInfo( file), [ for JsonValue.String( j) in jsonNames do yield j ]
248
247
249
- let resolveGoToImplementation ( unresolved : CodeLens , file : FileInfo , range : Range .range): CodeLens =
250
- let command =
248
+ let resolveGoToImplementation ( unresolved : CodeLens , file : FileInfo , range : Text .range): CodeLens =
249
+ let command =
251
250
{
252
251
title= sprintf " %s (%d )" file.Name range.StartLine
253
252
command= " fsharp.command.goto"
@@ -261,8 +260,8 @@ let resolveGoToImplementation(unresolved: CodeLens, file: FileInfo, range: Range
261
260
}
262
261
{ unresolved with command = Some( command) }
263
262
264
- let resolveMissingGoToImplementation ( unresolved : CodeLens , file : FileInfo ): CodeLens =
265
- let command =
263
+ let resolveMissingGoToImplementation ( unresolved : CodeLens , file : FileInfo ): CodeLens =
264
+ let command =
266
265
{
267
266
title= " Not Found"
268
267
command= " fsharp.command.goto"
@@ -276,7 +275,7 @@ let resolveMissingGoToImplementation(unresolved: CodeLens, file: FileInfo): Code
276
275
}
277
276
{ unresolved with command = Some( command) }
278
277
279
- let asRunTest ( fsproj : FileInfo , fullyQualifiedName : string list , test : Ast .SynBinding): CodeLens =
278
+ let asRunTest ( fsproj : FileInfo , fullyQualifiedName : string list , test : SyntaxTree .SynBinding): CodeLens =
280
279
{
281
280
range= asRange( test.RangeOfBindingSansRhs)
282
281
command= Some({ title= " Run Test"
@@ -285,11 +284,11 @@ let asRunTest(fsproj: FileInfo, fullyQualifiedName: string list, test: Ast.SynBi
285
284
data= JsonValue.Null
286
285
}
287
286
288
- let asDebugTest ( fsproj : FileInfo , fullyQualifiedName : string list , test : Ast .SynBinding): CodeLens =
287
+ let asDebugTest ( fsproj : FileInfo , fullyQualifiedName : string list , test : SyntaxTree .SynBinding): CodeLens =
289
288
{
290
289
range= asRange( test.RangeOfBindingSansRhs)
291
290
command= Some({ title= " Debug Test"
292
291
command= " fsharp.command.test.debug"
293
292
arguments=[ JsonValue.String( fsproj.FullName); JsonValue.String( String.concat " ." fullyQualifiedName)] })
294
293
data= JsonValue.Null
295
- }
294
+ }
0 commit comments