Skip to content

Commit

Permalink
Symbol Signature text API (#15275)
Browse files Browse the repository at this point in the history
* Proof of concept

* Update src/Compiler/Symbols/Symbols.fsi

---------

Co-authored-by: Petr <[email protected]>
  • Loading branch information
nojaf and psfinaki authored Jun 5, 2023
1 parent b441d77 commit 7abc6b5
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/Compiler/Symbols/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2355,6 +2355,33 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
|> LayoutRender.toArray
|> Some

member x.GetValSignatureText (displayContext: FSharpDisplayContext, m: range) =
checkIsResolved()
let stringValOfMethInfo methInfo =
match methInfo with
| FSMeth(valRef = vref) -> NicePrint.stringValOrMember (displayContext.Contents cenv.g) cenv.infoReader vref
| _ -> NicePrint.stringOfMethInfo cenv.infoReader m (displayContext.Contents cenv.g) methInfo

let stringValOfPropInfo (p: PropInfo) =
let t = p.GetPropertyType(cenv.amap, m ) |> NicePrint.layoutType (displayContext.Contents cenv.g) |> LayoutRender.showL
let withGetSet =
if p.HasGetter && p.HasSetter then "with get, set"
elif p.HasGetter then "with get"
elif p.HasSetter then "with set"
else ""

$"member val %s{p.DisplayName}: %s{t} %s{withGetSet}"

match d with
| E _ -> None
| V v ->
NicePrint.stringValOrMember (displayContext.Contents cenv.g) cenv.infoReader v
|> Some
| C methInfo
| M methInfo -> stringValOfMethInfo methInfo |> Some
| P p -> stringValOfPropInfo p |> Some


member x.GetWitnessPassingInfo() =
let witnessInfos =
match d with
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/Symbols/Symbols.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,9 @@ type FSharpMemberOrFunctionOrValue =
/// Format the type using the rules of the given display context
member GetReturnTypeLayout: displayContext: FSharpDisplayContext -> TaggedText[] option

/// Get the signature text to include this Symbol into an existing signature file.
member GetValSignatureText: displayContext: FSharpDisplayContext * m: range -> string option

/// Check if this method has an entrpoint that accepts witness arguments and if so return
/// the name of that entrypoint and information about the additional witness arguments
member GetWitnessPassingInfo: unit -> (string * IList<FSharpParameter>) option
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4959,6 +4959,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSh
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.Object] LiteralValue
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.Object] get_LiteralValue()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.String[]] TryGetFullCompiledOperatorNameIdents()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.String] GetValSignatureText(FSharp.Compiler.Symbols.FSharpDisplayContext, FSharp.Compiler.Text.Range)
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.String] TryGetFullDisplayName()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[System.String,System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpParameter]]] GetWitnessPassingInfo()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpAbstractSignature] ImplementedAbstractSignatures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4959,6 +4959,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSh
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.Object] LiteralValue
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.Object] get_LiteralValue()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.String[]] TryGetFullCompiledOperatorNameIdents()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.String] GetValSignatureText(FSharp.Compiler.Symbols.FSharpDisplayContext, FSharp.Compiler.Text.Range)
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.String] TryGetFullDisplayName()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[System.String,System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpParameter]]] GetWitnessPassingInfo()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpAbstractSignature] ImplementedAbstractSignatures
Expand Down
33 changes: 32 additions & 1 deletion tests/service/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -614,4 +614,35 @@ match Unchecked.defaultof<R> with
"""
getSymbolUses checkResults
|> Seq.exists (fun symbolUse -> symbolUse.IsFromUse && symbolUse.Symbol.DisplayName = "F2")
|> shouldEqual true
|> shouldEqual true

module GetValSignatureText =
let private assertSignature (expected:string) source (lineNumber, column, line, identifier) =
let _, checkResults = getParseAndCheckResults source
let symbolUseOpt = checkResults.GetSymbolUseAtLocation(lineNumber, column, line, [ identifier ])
match symbolUseOpt with
| None -> Assert.Fail "Expected symbol"
| Some symbolUse ->
match symbolUse.Symbol with
| :? FSharpMemberOrFunctionOrValue as mfv ->
let expected = expected.Replace("\r", "")
let signature = mfv.GetValSignatureText(symbolUse.DisplayContext, symbolUse.Range)
Assert.AreEqual(expected, signature.Value)
| symbol -> Assert.Fail $"Expected FSharpMemberOrFunctionOrValue, got %A{symbol}"

[<Test>]
let ``Signature text for let binding`` () =
assertSignature
"val a: b: int -> c: int -> int"
"let a b c = b + c"
(1, 4, "let a b c = b + c", "a")

[<Test>]
let ``Signature text for member binding`` () =
assertSignature
"member Bar: a: int -> b: int -> int"
"""
type Foo() =
member this.Bar (a:int) (b:int) : int = 0
"""
(3, 19, " member this.Bar (a:int) (b:int) : int = 0", "Bar")

0 comments on commit 7abc6b5

Please sign in to comment.