Skip to content

Commit

Permalink
Add GetSymbolUsesAtLocation API. (#15285)
Browse files Browse the repository at this point in the history
* Add GetSymbolUsesAtLocation API.

* Reuse new method in GetSymbolUseAtLocation.
  • Loading branch information
nojaf authored Jun 5, 2023
1 parent fd25719 commit b441d77
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 10 deletions.
42 changes: 38 additions & 4 deletions src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,36 @@ type internal TypeCheckInfo
Trace.TraceInformation(sprintf "FCS: recovering from error in GetSymbolUseAtLocation: '%s'" msg)
None)

member _.GetSymbolUsesAtLocation(line, lineStr, colAtEndOfNames, names) =
DiagnosticsScope.Protect
range0
(fun () ->
let declItemsOpt =
GetDeclItemsForNamesAtPosition(
None,
Some names,
None,
None,
line,
lineStr,
colAtEndOfNames,
ResolveTypeNamesToCtors,
ResolveOverloads.Yes,
None,
(fun () -> [])
)

match declItemsOpt with
| None -> List.empty
| Some (items, denv, _, m) ->
items
|> List.map (fun item ->
let symbol = FSharpSymbol.Create(cenv, item.Item)
symbol, item.ItemWithInst, denv, m))
(fun msg ->
Trace.TraceInformation(sprintf "FCS: recovering from error in GetSymbolUsesAtLocation: '%s'" msg)
List.empty)

member _.PartialAssemblySignatureForFile =
FSharpAssemblySignature(g, thisCcu, ccuSigForFile, tcImports, None, ccuSigForFile)

Expand Down Expand Up @@ -2796,12 +2826,16 @@ type FSharpCheckFileResults
| None -> emptyFindDeclResult
| Some (scope, _builderOpt) -> scope.GetDeclarationLocation(line, lineText, colAtEndOfNames, names, preferFlag)

member _.GetSymbolUseAtLocation(line, colAtEndOfNames, lineText, names) =
member this.GetSymbolUseAtLocation(line, colAtEndOfNames, lineText, names) =
this.GetSymbolUsesAtLocation(line, colAtEndOfNames, lineText, names)
|> List.tryHead

member _.GetSymbolUsesAtLocation(line, colAtEndOfNames, lineText, names) =
match details with
| None -> None
| None -> List.empty
| Some (scope, _builderOpt) ->
scope.GetSymbolUseAtLocation(line, lineText, colAtEndOfNames, names)
|> Option.map (fun (sym, itemWithInst, denv, m) ->
scope.GetSymbolUsesAtLocation(line, lineText, colAtEndOfNames, names)
|> List.map (fun (sym, itemWithInst, denv, m) ->
FSharpSymbolUse(denv, sym, itemWithInst.TyparInstantiation, ItemOccurence.Use, m))

member _.GetMethodsAsSymbols(line, colAtEndOfNames, lineText, names) =
Expand Down
9 changes: 9 additions & 0 deletions src/Compiler/Service/FSharpCheckerResults.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,15 @@ type public FSharpCheckFileResults =
member GetSymbolUseAtLocation:
line: int * colAtEndOfNames: int * lineText: string * names: string list -> FSharpSymbolUse option

/// <summary>Similar to GetSymbolUseAtLocation, but returns all found symbols if there are multiple.</summary>
///
/// <param name="line">The line number where the information is being requested.</param>
/// <param name="colAtEndOfNames">The column number at the end of the identifiers where the information is being requested.</param>
/// <param name="lineText">The text of the line where the information is being requested.</param>
/// <param name="names">The identifiers at the location where the information is being requested.</param>
member GetSymbolUsesAtLocation:
line: int * colAtEndOfNames: int * lineText: string * names: string list -> FSharpSymbolUse list

/// <summary>Get any extra colorization info that is available after the typecheck</summary>
member GetSemanticClassification: range option -> SemanticClassificationItem[]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2005,6 +2005,7 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSh
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSharpOpenDeclaration[] OpenDeclarations
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSharpOpenDeclaration[] get_OpenDeclarations()
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Text.Range[] GetFormatSpecifierLocations()
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse] GetSymbolUsesAtLocation(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse]] GetDeclarationListSymbols(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults], Int32, System.String, FSharp.Compiler.EditorServices.PartialLongName, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.AssemblySymbol]]])
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse] GetSymbolUseAtLocation(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpDisplayContext] GetDisplayContextForPos(FSharp.Compiler.Text.Position)
Expand Down Expand Up @@ -5156,14 +5157,14 @@ FSharp.Compiler.Symbols.FSharpUnionCase: Boolean get_HasFields()
FSharp.Compiler.Symbols.FSharpUnionCase: Boolean get_IsUnresolved()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpAccessibility Accessibility
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpAccessibility get_Accessibility()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity DeclaringEntity
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity get_DeclaringEntity()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpType ReturnType
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpType get_ReturnType()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpXmlDoc XmlDoc
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpXmlDoc get_XmlDoc()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Text.Range DeclarationLocation
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Text.Range get_DeclarationLocation()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity DeclaringEntity
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity get_DeclaringEntity()
FSharp.Compiler.Symbols.FSharpUnionCase: Int32 GetHashCode()
FSharp.Compiler.Symbols.FSharpUnionCase: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpAttribute] Attributes
FSharp.Compiler.Symbols.FSharpUnionCase: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpAttribute] get_Attributes()
Expand Down Expand Up @@ -11375,4 +11376,4 @@ FSharp.Compiler.Xml.XmlDoc: System.String GetXmlText()
FSharp.Compiler.Xml.XmlDoc: System.String[] GetElaboratedXmlLines()
FSharp.Compiler.Xml.XmlDoc: System.String[] UnprocessedLines
FSharp.Compiler.Xml.XmlDoc: System.String[] get_UnprocessedLines()
FSharp.Compiler.Xml.XmlDoc: Void .ctor(System.String[], FSharp.Compiler.Text.Range)
FSharp.Compiler.Xml.XmlDoc: Void .ctor(System.String[], FSharp.Compiler.Text.Range)
Original file line number Diff line number Diff line change
Expand Up @@ -2005,6 +2005,7 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSh
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSharpOpenDeclaration[] OpenDeclarations
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSharpOpenDeclaration[] get_OpenDeclarations()
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Text.Range[] GetFormatSpecifierLocations()
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse] GetSymbolUsesAtLocation(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse]] GetDeclarationListSymbols(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults], Int32, System.String, FSharp.Compiler.EditorServices.PartialLongName, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.AssemblySymbol]]])
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse] GetSymbolUseAtLocation(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpDisplayContext] GetDisplayContextForPos(FSharp.Compiler.Text.Position)
Expand Down Expand Up @@ -5156,14 +5157,14 @@ FSharp.Compiler.Symbols.FSharpUnionCase: Boolean get_HasFields()
FSharp.Compiler.Symbols.FSharpUnionCase: Boolean get_IsUnresolved()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpAccessibility Accessibility
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpAccessibility get_Accessibility()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity DeclaringEntity
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity get_DeclaringEntity()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpType ReturnType
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpType get_ReturnType()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpXmlDoc XmlDoc
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpXmlDoc get_XmlDoc()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Text.Range DeclarationLocation
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Text.Range get_DeclarationLocation()
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity DeclaringEntity
FSharp.Compiler.Symbols.FSharpUnionCase: FSharp.Compiler.Symbols.FSharpEntity get_DeclaringEntity()
FSharp.Compiler.Symbols.FSharpUnionCase: Int32 GetHashCode()
FSharp.Compiler.Symbols.FSharpUnionCase: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpAttribute] Attributes
FSharp.Compiler.Symbols.FSharpUnionCase: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpAttribute] get_Attributes()
Expand Down
50 changes: 49 additions & 1 deletion tests/service/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,54 @@ type Foo =
(:? FSharpMemberOrFunctionOrValue as setMfv) ->
Assert.AreNotEqual(getMfv.CurriedParameterGroups, setMfv.CurriedParameterGroups)
| _ -> Assert.Fail "Expected symbols to be FSharpMemberOrFunctionOrValue"

[<Test>]
let ``Multiple symbols are resolved for property`` () =
let source = """
type X(y: string) =
member val Y = y with get, set
"""

let _, checkResults = getParseAndCheckResults source
let symbolUses =
checkResults.GetSymbolUsesAtLocation(3, 16, " member val Y = y with get, set", [ "Y" ])
|> List.map (fun su -> su.Symbol)

match symbolUses with
| [ :? FSharpMemberOrFunctionOrValue as setMfv
:? FSharpMemberOrFunctionOrValue as getMfv ] ->
Assert.AreEqual("set_Y", setMfv.CompiledName)
Assert.AreEqual("get_Y", getMfv.CompiledName)
| _ -> Assert.Fail "Expected symbols"

[<Test>]
let ``Multiple relevant symbols for type name`` () =
let _, checkResults = getParseAndCheckResults """
// This is a generated file; the original input is 'FSInteractiveSettings.txt'
namespace FSInteractiveSettings
type internal SR () =
static let mutable swallowResourceText = false
/// If set to true, then all error messages will just return the filled 'holes' delimited by ',,,'s - this is for language-neutral testing (e.g. localization-invariant baselines).
static member SwallowResourceText with get () = swallowResourceText
and set (b) = swallowResourceText <- b
// END BOILERPLATE
"""

let symbols =
checkResults.GetSymbolUsesAtLocation(5, 16, "type internal SR () =", [ "" ])
|> List.map (fun su -> su.Symbol)

match symbols with
| [ :? FSharpMemberOrFunctionOrValue as cctor
:? FSharpMemberOrFunctionOrValue as ctor
:? FSharpEntity as entity ] ->
Assert.AreEqual(".cctor", cctor.CompiledName)
Assert.AreEqual(".ctor", ctor.CompiledName)
Assert.AreEqual("SR", entity.DisplayName)
| _ -> Assert.Fail "Expected symbols"

module Expressions =
[<Test>]
Expand Down Expand Up @@ -566,4 +614,4 @@ match Unchecked.defaultof<R> with
"""
getSymbolUses checkResults
|> Seq.exists (fun symbolUse -> symbolUse.IsFromUse && symbolUse.Symbol.DisplayName = "F2")
|> shouldEqual true
|> shouldEqual true

0 comments on commit b441d77

Please sign in to comment.