From 0b9218c8bd06644947d90789a0dc0b288b6f94f1 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 1 Jun 2023 09:49:40 +0200 Subject: [PATCH 1/2] Add GetSymbolUsesAtLocation API. --- src/Compiler/Service/FSharpCheckerResults.fs | 38 ++++++++++++++ src/Compiler/Service/FSharpCheckerResults.fsi | 9 ++++ ...ervice.SurfaceArea.netstandard20.debug.bsl | 7 +-- ...vice.SurfaceArea.netstandard20.release.bsl | 5 +- tests/service/Symbols.fs | 50 ++++++++++++++++++- 5 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index e2feb604bad..be6d4cc1a78 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -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) @@ -2804,6 +2834,14 @@ type FSharpCheckFileResults |> Option.map (fun (sym, itemWithInst, denv, m) -> FSharpSymbolUse(denv, sym, itemWithInst.TyparInstantiation, ItemOccurence.Use, m)) + member _.GetSymbolUsesAtLocation(line, colAtEndOfNames, lineText, names) = + match details with + | None -> List.empty + | Some (scope, _builderOpt) -> + 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) = match details with | None -> None diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi index c2e1cec1e4a..81d50d90b78 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fsi +++ b/src/Compiler/Service/FSharpCheckerResults.fsi @@ -383,6 +383,15 @@ type public FSharpCheckFileResults = member GetSymbolUseAtLocation: line: int * colAtEndOfNames: int * lineText: string * names: string list -> FSharpSymbolUse option + /// Similar to GetSymbolUseAtLocation, but returns all found symbols if there are multiple. + /// + /// The line number where the information is being requested. + /// The column number at the end of the identifiers where the information is being requested. + /// The text of the line where the information is being requested. + /// The identifiers at the location where the information is being requested. + member GetSymbolUsesAtLocation: + line: int * colAtEndOfNames: int * lineText: string * names: string list -> FSharpSymbolUse list + /// Get any extra colorization info that is available after the typecheck member GetSemanticClassification: range option -> SemanticClassificationItem[] diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 2bf927ac27b..01632a9387b 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -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) @@ -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() @@ -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) \ No newline at end of file diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 57f794c68b4..9b438a80224 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -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) @@ -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() diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 71594bc81bf..a2f93ea5366 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -474,6 +474,54 @@ type Foo = (:? FSharpMemberOrFunctionOrValue as setMfv) -> Assert.AreNotEqual(getMfv.CurriedParameterGroups, setMfv.CurriedParameterGroups) | _ -> Assert.Fail "Expected symbols to be FSharpMemberOrFunctionOrValue" + + [] + 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" + + [] + 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 = [] @@ -566,4 +614,4 @@ match Unchecked.defaultof with """ getSymbolUses checkResults |> Seq.exists (fun symbolUse -> symbolUse.IsFromUse && symbolUse.Symbol.DisplayName = "F2") - |> shouldEqual true + |> shouldEqual true \ No newline at end of file From 60e430a667a1aedf379328f26565f626a01790d3 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 1 Jun 2023 13:21:52 +0200 Subject: [PATCH 2/2] Reuse new method in GetSymbolUseAtLocation. --- src/Compiler/Service/FSharpCheckerResults.fs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index be6d4cc1a78..1767eb06145 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -2826,13 +2826,9 @@ type FSharpCheckFileResults | None -> emptyFindDeclResult | Some (scope, _builderOpt) -> scope.GetDeclarationLocation(line, lineText, colAtEndOfNames, names, preferFlag) - member _.GetSymbolUseAtLocation(line, colAtEndOfNames, lineText, names) = - match details with - | None -> None - | Some (scope, _builderOpt) -> - scope.GetSymbolUseAtLocation(line, lineText, colAtEndOfNames, names) - |> Option.map (fun (sym, itemWithInst, denv, m) -> - FSharpSymbolUse(denv, sym, itemWithInst.TyparInstantiation, ItemOccurence.Use, m)) + member this.GetSymbolUseAtLocation(line, colAtEndOfNames, lineText, names) = + this.GetSymbolUsesAtLocation(line, colAtEndOfNames, lineText, names) + |> List.tryHead member _.GetSymbolUsesAtLocation(line, colAtEndOfNames, lineText, names) = match details with