Skip to content

Commit

Permalink
Symbols: Add GenericArguments to FSharpEntity (#16470)
Browse files Browse the repository at this point in the history
* Symbols: Add GenericArguments to FSharpEntity

* Update surface area

* Release notes

* Keep type args in mfv.ApparentEnclosingEntity
  • Loading branch information
auduchinok authored Feb 7, 2024
1 parent 3ac064e commit 0de949c
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 35 deletions.
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/8.0.300.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Name resolution: keep type vars in subsequent checks ([PR #16456](https://github.com/dotnet/fsharp/pull/16456))
* Higher-order-function-based API for working with the untyped abstract syntax tree. ([PR #16462](https://github.com/dotnet/fsharp/pull/16462))
* Allow returning bool instead of unit option for partial active patterns. ([Language suggestion #1041](https://github.com/fsharp/fslang-suggestions/issues/1041), [PR #16473](https://github.com/dotnet/fsharp/pull/16473))
* Symbols: Add GenericArguments to FSharpEntity ([PR #16470](https://github.com/dotnet/fsharp/pull/16470))

### Changed

Expand Down
12 changes: 6 additions & 6 deletions src/Compiler/Checking/NameResolution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ type Item =
| Item.CtorGroup(nm, _) -> nm |> DemangleGenericTypeName
| Item.DelegateCtor ty ->
match ty with
| AbbrevOrAppTy tcref -> tcref.DisplayNameCore
| AbbrevOrAppTy(tcref, _) -> tcref.DisplayNameCore
// This case is not expected
| _ -> ""
| Item.UnqualifiedType(tcref :: _) -> tcref.DisplayNameCore
Expand Down Expand Up @@ -309,7 +309,7 @@ type Item =
| Item.Property(info = pinfo :: _) -> pinfo.DisplayName
| Item.Event einfo -> einfo.DisplayName
| Item.MethodGroup(_, minfo :: _, _) -> minfo.DisplayName
| Item.DelegateCtor (AbbrevOrAppTy tcref) -> tcref.DisplayName
| Item.DelegateCtor (AbbrevOrAppTy(tcref, _)) -> tcref.DisplayName
| Item.UnqualifiedType(tcref :: _) -> tcref.DisplayName
| Item.ModuleOrNamespaces(modref :: _) -> modref.DisplayName
| Item.TypeVar (nm, _) -> nm |> ConvertLogicalNameToDisplayName
Expand Down Expand Up @@ -1872,11 +1872,11 @@ let (|EntityUse|_|) (item: Item) =
match item with
| Item.UnqualifiedType (tcref :: _) -> ValueSome tcref
| Item.ExnCase tcref -> ValueSome tcref
| Item.Types(_, [AbbrevOrAppTy tcref])
| Item.DelegateCtor(AbbrevOrAppTy tcref) -> ValueSome tcref
| Item.Types(_, [AbbrevOrAppTy(tcref, _)])
| Item.DelegateCtor(AbbrevOrAppTy(tcref, _)) -> ValueSome tcref
| Item.CtorGroup(_, ctor :: _) ->
match ctor.ApparentEnclosingType with
| AbbrevOrAppTy tcref -> ValueSome tcref
| AbbrevOrAppTy(tcref, _) -> ValueSome tcref
| _ -> ValueNone
| _ -> ValueNone

Expand Down Expand Up @@ -1958,7 +1958,7 @@ let ItemsAreEffectivelyEqual g orig other =
not tp1.IsCompilerGenerated && not tp1.IsFromError &&
not tp2.IsCompilerGenerated && not tp2.IsFromError &&
equals tp1.Range tp2.Range
| AbbrevOrAppTy tcref1, AbbrevOrAppTy tcref2 ->
| AbbrevOrAppTy(tcref1, _), AbbrevOrAppTy(tcref2, _) ->
tyconRefDefnEq g tcref1 tcref2
| _ -> false)

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/infos.fs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ type MethInfo =
member x.DebuggerDisplayName =
match x with
| ILMeth(_, y, _) -> y.DeclaringTyconRef.DisplayNameWithStaticParametersAndUnderscoreTypars + "::" + y.ILName
| FSMeth(_, AbbrevOrAppTy tcref, vref, _) -> tcref.DisplayNameWithStaticParametersAndUnderscoreTypars + "::" + vref.LogicalName
| FSMeth(_, AbbrevOrAppTy(tcref, _), vref, _) -> tcref.DisplayNameWithStaticParametersAndUnderscoreTypars + "::" + vref.LogicalName
| FSMeth(_, _, vref, _) -> "??::" + vref.LogicalName
#if !NO_TYPEPROVIDERS
| ProvidedMeth(_, mi, _, m) -> "ProvidedMeth: " + mi.PUntaint((fun mi -> mi.Name), m)
Expand Down
8 changes: 4 additions & 4 deletions src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1805,9 +1805,9 @@ type internal TypeCheckInfo
|> List.sortBy (fun d ->
let n =
match d.Item with
| Item.Types(_, AbbrevOrAppTy tcref :: _) -> 1 + tcref.TyparsNoRange.Length
| Item.Types(_, AbbrevOrAppTy(tcref, _) :: _) -> 1 + tcref.TyparsNoRange.Length
// Put delegate ctors after types, sorted by #typars. RemoveDuplicateItems will remove FakeInterfaceCtor and DelegateCtor if an earlier type is also reported with this name
| Item.DelegateCtor(AbbrevOrAppTy tcref) -> 1000 + tcref.TyparsNoRange.Length
| Item.DelegateCtor(AbbrevOrAppTy(tcref, _)) -> 1000 + tcref.TyparsNoRange.Length
// Put type ctors after types, sorted by #typars. RemoveDuplicateItems will remove DefaultStructCtors if a type is also reported with this name
| Item.CtorGroup(_, cinfo :: _) -> 1000 + 10 * cinfo.DeclaringTyconRef.TyparsNoRange.Length
| _ -> 0
Expand All @@ -1823,10 +1823,10 @@ type internal TypeCheckInfo
items
|> List.groupBy (fun d ->
match d.Item with
| Item.Types(_, AbbrevOrAppTy tcref :: _)
| Item.Types(_, AbbrevOrAppTy(tcref, _) :: _)
| Item.ExnCase tcref -> tcref.LogicalName
| Item.UnqualifiedType(tcref :: _)
| Item.DelegateCtor(AbbrevOrAppTy tcref) -> tcref.CompiledName
| Item.DelegateCtor(AbbrevOrAppTy(tcref, _)) -> tcref.CompiledName
| Item.CtorGroup(_, cinfo :: _) -> cinfo.ApparentEnclosingTyconRef.CompiledName
| _ -> d.Item.DisplayName)

Expand Down
8 changes: 4 additions & 4 deletions src/Compiler/Symbols/SymbolHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ module internal SymbolHelpers =
| Item.DelegateCtor ty
| Item.Types(_, ty :: _) ->
match ty with
| AbbrevOrAppTy tcref ->
| AbbrevOrAppTy(tcref, _) ->
mkXmlComment (GetXmlDocSigOfEntityRef infoReader m tcref)
| _ -> FSharpXmlDoc.None

Expand Down Expand Up @@ -462,8 +462,8 @@ module internal SymbolHelpers =
| Item.UnqualifiedType tcrefs1, Item.UnqualifiedType tcrefs2 ->
(tcrefs1, tcrefs2)
||> List.forall2 (fun tcref1 tcref2 -> tyconRefEq g tcref1 tcref2)
| Item.Types(_, [AbbrevOrAppTy tcref1]), Item.UnqualifiedType([tcref2]) -> tyconRefEq g tcref1 tcref2
| Item.UnqualifiedType([tcref1]), Item.Types(_, [AbbrevOrAppTy tcref2]) -> tyconRefEq g tcref1 tcref2
| Item.Types(_, [AbbrevOrAppTy(tcref1, _)]), Item.UnqualifiedType([tcref2]) -> tyconRefEq g tcref1 tcref2
| Item.UnqualifiedType([tcref1]), Item.Types(_, [AbbrevOrAppTy(tcref2, _)]) -> tyconRefEq g tcref1 tcref2
| _ -> false)

member x.GetHashCode item =
Expand Down Expand Up @@ -648,7 +648,7 @@ module internal SymbolHelpers =
| Item.Types(_, tys) ->
let doc =
match tys with
| AbbrevOrAppTy tcref :: _ ->
| AbbrevOrAppTy(tcref, _) :: _ ->
if tyconRefUsesLocalXmlDoc g.compilingFSharpCore tcref || tcref.XmlDoc.NonEmpty then
Some tcref.XmlDoc
else
Expand Down
40 changes: 26 additions & 14 deletions src/Compiler/Symbols/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,12 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C
| Item.CtorGroup(_, cinfo :: _) ->
FSharpMemberOrFunctionOrValue(cenv, C cinfo, item) :> _

| Item.DelegateCtor (AbbrevOrAppTy tcref) ->
FSharpEntity(cenv, tcref) :>_
| Item.DelegateCtor (AbbrevOrAppTy(tcref, tyargs))
| Item.Types(_, AbbrevOrAppTy(tcref, tyargs) :: _) ->
FSharpEntity(cenv, tcref, tyargs) :>_

| Item.UnqualifiedType(tcref :: _)
| Item.Types(_, AbbrevOrAppTy tcref :: _) ->
FSharpEntity(cenv, tcref) :>_
| Item.UnqualifiedType(tcref :: _) ->
FSharpEntity(cenv, tcref) :> _

| Item.ModuleOrNamespaces(modref :: _) ->
FSharpEntity(cenv, modref) :> _
Expand Down Expand Up @@ -355,7 +355,7 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C
member sym.TryGetAttribute<'T>() =
sym.Attributes |> Seq.tryFind (fun attr -> attr.IsAttribute<'T>())

type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) =
type FSharpEntity(cenv: SymbolEnv, entity: EntityRef, tyargs: TType list) =
inherit FSharpSymbol(cenv,
(fun () ->
checkEntityIsResolved entity
Expand Down Expand Up @@ -383,6 +383,10 @@ type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) =
| None -> false
| Some ccu -> ccuEq ccu cenv.g.fslibCcu

new(cenv: SymbolEnv, tcref: TyconRef) =
let _, _, tyargs = FreshenTypeInst cenv.g range0 (tcref.Typars range0)
FSharpEntity(cenv, tcref, tyargs)

member _.Entity = entity

member _.LogicalName =
Expand Down Expand Up @@ -480,6 +484,10 @@ type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) =
checkIsResolved()
entity.TyparsNoRange |> List.map (fun tp -> FSharpGenericParameter(cenv, tp)) |> makeReadOnlyCollection

member _.GenericArguments =
checkIsResolved()
tyargs |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection

member _.IsMeasure =
isResolvedAndFSharp() && (entity.TypeOrMeasureKind = TyparKind.Measure)

Expand Down Expand Up @@ -718,7 +726,7 @@ type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) =
if isUnresolved() then makeReadOnlyCollection [] else
entity.ModuleOrNamespaceType.AllEntities
|> QueueList.toList
|> List.map (fun x -> FSharpEntity(cenv, entity.NestedTyconRef x))
|> List.map (fun x -> FSharpEntity(cenv, entity.NestedTyconRef x, tyargs))
|> makeReadOnlyCollection

member _.UnionCases =
Expand Down Expand Up @@ -1688,7 +1696,7 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
| Some v -> v
| None -> failwith "DeclarationLocation property not available"

member _.DeclaringEntity =
member _.DeclaringEntity: FSharpEntity option =
checkIsResolved()
match d with
| E e -> FSharpEntity(cenv, e.DeclaringTyconRef) |> Some
Expand All @@ -1699,12 +1707,16 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
| ParentNone -> None
| Parent p -> FSharpEntity(cenv, p) |> Some

member _.ApparentEnclosingEntity =
member _.ApparentEnclosingEntity: FSharpEntity =
let createEntity (ttype: TType) =
let tcref, tyargs = destAppTy cenv.g ttype
FSharpEntity(cenv, tcref, tyargs)

checkIsResolved()
match d with
| E e -> FSharpEntity(cenv, e.ApparentEnclosingTyconRef)
| P p -> FSharpEntity(cenv, p.ApparentEnclosingTyconRef)
| M m | C m -> FSharpEntity(cenv, m.ApparentEnclosingTyconRef)
| E e -> createEntity e.ApparentEnclosingType
| P p -> createEntity p.ApparentEnclosingType
| M m | C m -> createEntity m.ApparentEnclosingType
| V v ->
match v.ApparentEnclosingEntity with
| ParentNone -> invalidOp "the value or member doesn't have a logical parent"
Expand Down Expand Up @@ -2453,7 +2465,7 @@ type FSharpType(cenv, ty:TType) =
let isUnresolved() =
DiagnosticsLogger.protectAssemblyExploration true <| fun () ->
match stripTyparEqns ty with
| TType_app (tcref, _, _) -> FSharpEntity(cenv, tcref).IsUnresolved
| TType_app (tcref, tyargs, _) -> FSharpEntity(cenv, tcref, tyargs).IsUnresolved
| TType_measure (Measure.Const tcref) -> FSharpEntity(cenv, tcref).IsUnresolved
| TType_measure (Measure.Prod _) -> FSharpEntity(cenv, cenv.g.measureproduct_tcr).IsUnresolved
| TType_measure Measure.One -> FSharpEntity(cenv, cenv.g.measureone_tcr).IsUnresolved
Expand Down Expand Up @@ -2497,7 +2509,7 @@ type FSharpType(cenv, ty:TType) =
member _.TypeDefinition =
protect <| fun () ->
match stripTyparEqns ty with
| TType_app (tcref, _, _) -> FSharpEntity(cenv, tcref)
| TType_app (tcref, tyargs, _) -> FSharpEntity(cenv, tcref, tyargs)
| TType_measure (Measure.Const tcref) -> FSharpEntity(cenv, tcref)
| TType_measure (Measure.Prod _) -> FSharpEntity(cenv, cenv.g.measureproduct_tcr)
| TType_measure Measure.One -> FSharpEntity(cenv, cenv.g.measureone_tcr)
Expand Down
4 changes: 4 additions & 0 deletions src/Compiler/Symbols/Symbols.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ type FSharpEntity =

/// Get the generic parameters, possibly including unit-of-measure parameters
member GenericParameters: IList<FSharpGenericParameter>

/// Get the generic parameters, possibly including unit-of-measure parameters
member GenericArguments: IList<FSharpType>

#if !NO_TYPEPROVIDERS
/// Get the static parameters for a provided type
member StaticParameters: IList<FSharpStaticParameter>
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/TypedTree/TypedTreeBasics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ let stripUnitEqns unt = stripUnitEqnsAux false unt
/// Detect a use of a nominal type, including type abbreviations.
let (|AbbrevOrAppTy|_|) (ty: TType) =
match stripTyparEqns ty with
| TType_app (tcref, _, _) -> Some tcref
| TType_app (tcref, tinst, _) -> Some(tcref, tinst)
| _ -> None

//---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/TypedTree/TypedTreeBasics.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ val stripTyparEqns: ty: TType -> TType
val stripUnitEqns: unt: Measure -> Measure

/// Detect a use of a nominal type, including type abbreviations.
val (|AbbrevOrAppTy|_|): ty: TType -> TyconRef option
val (|AbbrevOrAppTy|_|): ty: TType -> (TyconRef * TypeInst) option

val mkLocalValRef: v: Val -> ValRef

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4868,8 +4868,10 @@ FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpStaticParameter] get_StaticParameters()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] AllInterfaces
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] DeclaredInterfaces
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] GenericArguments
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_AllInterfaces()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_DeclaredInterfaces()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_GenericArguments()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] UnionCases
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] get_UnionCases()
FSharp.Compiler.Symbols.FSharpEntity: System.String AccessPath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4868,8 +4868,10 @@ FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpStaticParameter] get_StaticParameters()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] AllInterfaces
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] DeclaredInterfaces
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] GenericArguments
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_AllInterfaces()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_DeclaredInterfaces()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_GenericArguments()
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] UnionCases
FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] get_UnionCases()
FSharp.Compiler.Symbols.FSharpEntity: System.String AccessPath
Expand Down
19 changes: 15 additions & 4 deletions tests/service/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -327,15 +327,16 @@ open System
findSymbolUseByName "IDisposable" checkResults |> ignore


[<Test; Explicit>]
[<Test>]
let ``Interface 04 - Type arg`` () =
let _, checkResults = getParseAndCheckResults """
open System.Collections.Generic
IList<int>
"""
let symbolUse = findSymbolUseByName "IList`1" checkResults
let _, typeArg = symbolUse.GenericArguments[0]
let symbol = symbolUse.Symbol :?> FSharpEntity
let typeArg = symbol.GenericArguments[0]
typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int"

[<Test>]
Expand All @@ -351,7 +352,8 @@ type I<'T> =
getSymbolUses checkResults
|> Seq.findBack (fun symbolUse -> symbolUse.Symbol.DisplayName = "I")

let _, typeArg = symbolUse.GenericArguments[0]
let symbol = symbolUse.Symbol :?> FSharpEntity
let typeArg = symbol.GenericArguments[0]
typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int"

[<Test>]
Expand All @@ -367,9 +369,18 @@ type I<'T> =
getSymbolUses checkResults
|> Seq.findBack (fun symbolUse -> symbolUse.Symbol.DisplayName = "I")

let _, typeArg = symbolUse.GenericArguments[0]
let symbol = symbolUse.Symbol :?> FSharpEntity
let typeArg = symbol.GenericArguments[0]
typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int"

[<Test>]
let ``Operator 01 - Type arg`` () =
let _, checkResults = getParseAndCheckResults """
[1] |> ignore
"""
let symbolUses = checkResults.GetAllUsesOfAllSymbolsInFile()
()

[<Test>]
let ``FSharpType.Format can use prefix representations`` () =
let _, checkResults = getParseAndCheckResults """
Expand Down

0 comments on commit 0de949c

Please sign in to comment.