Skip to content

Commit 1ae73fe

Browse files
committed
Merge pull request #426 from dsyme/fix-423
fix 423 (Events), fix 235 (XmlDocSig)
2 parents 92c68a4 + 04b4d6f commit 1ae73fe

File tree

4 files changed

+99
-41
lines changed

4 files changed

+99
-41
lines changed

src/fsharp/vs/Symbols.fs

+53-11
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ module Impl =
4141
System.Collections.ObjectModel.ReadOnlyCollection<_>(Seq.toArray arr) :> IList<_>
4242
let makeXmlDoc (XmlDoc x) = makeReadOnlyCollection (x)
4343

44-
let rescopeEntity viewedCcu (entity : Entity) =
44+
let rescopeEntity optViewedCcu (entity : Entity) =
45+
match optViewedCcu with
46+
| None -> mkLocalEntityRef entity
47+
| Some viewedCcu ->
4548
match tryRescopeEntity viewedCcu entity with
4649
| None -> mkLocalEntityRef entity
4750
| Some eref -> eref
@@ -1115,9 +1118,37 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
11151118
| P m ->
11161119
let minfo = m.GetterMethod
11171120
FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
1118-
| E _
1119-
| M _
1120-
| V _ -> invalidOp "the value or member doesn't have an associated getter method"
1121+
| E _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated getter method"
1122+
1123+
member __.EventAddMethod =
1124+
checkIsResolved()
1125+
match d with
1126+
| E e ->
1127+
let minfo = e.GetAddMethod()
1128+
FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
1129+
| P _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated add method"
1130+
1131+
member __.EventRemoveMethod =
1132+
checkIsResolved()
1133+
match d with
1134+
| E e ->
1135+
let minfo = e.GetRemoveMethod()
1136+
FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
1137+
| P _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated remove method"
1138+
1139+
member __.EventDelegateType =
1140+
checkIsResolved()
1141+
match d with
1142+
| E e -> FSharpType(cenv, e.GetDelegateType(cenv.amap,range0))
1143+
| P _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated event delegate type"
1144+
1145+
member __.EventIsStandard =
1146+
checkIsResolved()
1147+
match d with
1148+
| E e ->
1149+
let dty = e.GetDelegateType(cenv.amap,range0)
1150+
TryDestStandardDelegateTyp cenv.infoReader range0 AccessibleFromSomewhere dty |> isSome
1151+
| P _ | M _ | V _ -> invalidOp "the value or member is not an event"
11211152

11221153
member __.HasSetterMethod =
11231154
if isUnresolved() then false
@@ -1446,9 +1477,15 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
14461477
| E e ->
14471478
// INCOMPLETENESS: Attribs is empty here, so we can't look at return attributes for .NET or F# methods
14481479
let retInfo : ArgReprInfo = { Name=None; Attribs= [] }
1449-
let rty = PropTypOfEventInfo cenv.infoReader range0 AccessibleFromSomewhere e
1450-
let _,rty, _cxs = PrettyTypes.PrettifyTypes1 cenv.g rty
1480+
let rty =
1481+
try PropTypOfEventInfo cenv.infoReader range0 AccessibleFromSomewhere e
1482+
with _ ->
1483+
// For non-standard events, just use the delegate type as the ReturnParameter type
1484+
e.GetDelegateType(cenv.amap,range0)
1485+
1486+
let _, rty, _cxs = PrettyTypes.PrettifyTypes1 cenv.g rty
14511487
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isOutArg=false, isOptionalArg=false)
1488+
14521489
| P p ->
14531490
// INCOMPLETENESS: Attribs is empty here, so we can't look at return attributes for .NET or F# methods
14541491
let retInfo : ArgReprInfo = { Name=None; Attribs= [] }
@@ -1813,9 +1850,13 @@ and FSharpParameter(cenv, typ:TType, topArgInfo:ArgReprInfo, mOpt, isParamArrayA
18131850
override x.ToString() =
18141851
"parameter " + (match x.Name with None -> "<unnamed" | Some s -> s)
18151852

1816-
and FSharpAssemblySignature internal (cenv, topAttribs: TypeChecker.TopAttribs option, mtyp: ModuleOrNamespaceType) =
1853+
and FSharpAssemblySignature private (cenv, topAttribs: TypeChecker.TopAttribs option, optViewedCcu: CcuThunk option, mtyp: ModuleOrNamespaceType) =
18171854

1818-
new (g, thisCcu, tcImports, topAttribs, mtyp) = FSharpAssemblySignature(cenv(g,thisCcu,tcImports), topAttribs, mtyp)
1855+
// Assembly signature for a referenced/linked assembly
1856+
new (cenv, ccu: CcuThunk) = FSharpAssemblySignature((if ccu.IsUnresolvedReference then cenv else (new cenv(cenv.g, ccu, cenv.tcImports))), None, Some ccu, ccu.Contents.ModuleOrNamespaceType)
1857+
1858+
// Assembly signature for an assembly produced via type-checking.
1859+
new (g, thisCcu, tcImports, topAttribs, mtyp) = FSharpAssemblySignature(cenv(g, thisCcu, tcImports), topAttribs, None, mtyp)
18191860

18201861
member __.Entities =
18211862

@@ -1824,7 +1865,8 @@ and FSharpAssemblySignature internal (cenv, topAttribs: TypeChecker.TopAttribs o
18241865
if entity.IsNamespace then
18251866
yield! loop entity.ModuleOrNamespaceType
18261867
else
1827-
yield FSharpEntity(cenv, mkLocalEntityRef entity) |]
1868+
let entityRef = rescopeEntity optViewedCcu entity
1869+
yield FSharpEntity(cenv, entityRef) |]
18281870

18291871
loop mtyp |> makeReadOnlyCollection
18301872

@@ -1839,15 +1881,15 @@ and FSharpAssemblySignature internal (cenv, topAttribs: TypeChecker.TopAttribs o
18391881

18401882
and FSharpAssembly internal (cenv, ccu: CcuThunk) =
18411883

1842-
new (g, thisCcu, tcImports, ccu) = FSharpAssembly(cenv(g,thisCcu,tcImports), ccu)
1884+
new (g, tcImports, ccu) = FSharpAssembly(cenv(g, ccu, tcImports), ccu)
18431885

18441886
member __.RawCcuThunk = ccu
18451887
member __.QualifiedName = match ccu.QualifiedName with None -> "" | Some s -> s
18461888
member __.CodeLocation = ccu.SourceCodeDirectory
18471889
member __.FileName = ccu.FileName
18481890
member __.SimpleName = ccu.AssemblyName
18491891
member __.IsProviderGenerated = ccu.IsProviderGenerated
1850-
member __.Contents = FSharpAssemblySignature((if ccu.IsUnresolvedReference then cenv else (new cenv(cenv.g, ccu, cenv.tcImports))), None, ccu.Contents.ModuleOrNamespaceType)
1892+
member __.Contents = FSharpAssemblySignature(cenv, ccu)
18511893

18521894
override x.ToString() = x.QualifiedName
18531895

src/fsharp/vs/Symbols.fsi

+17-3
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ type [<Class>] FSharpSymbol =
8080
/// Represents an assembly as seen by the F# language
8181
and [<Class>] FSharpAssembly =
8282

83-
internal new : tcGlobals: TcGlobals * thisCcu: CcuThunk * tcImports: TcImports * ccu: CcuThunk -> FSharpAssembly
83+
internal new : tcGlobals: TcGlobals * tcImports: TcImports * ccu: CcuThunk -> FSharpAssembly
8484

8585
/// The qualified name of the assembly
8686
member QualifiedName: string
@@ -623,18 +623,32 @@ and [<Class>] FSharpMemberOrFunctionOrValue =
623623
/// Indicates if this is a property member
624624
member IsProperty : bool
625625

626-
/// Indicates if this is a property then there exists an associated getter method
626+
/// Indicates if this is a property and there exists an associated getter method
627627
member HasGetterMethod : bool
628628

629629
/// Get an associated getter method of the property
630630
member GetterMethod : FSharpMemberOrFunctionOrValue
631631

632-
/// Indicates if this is a property then there exists an associated setter method
632+
/// Indicates if this is a property and there exists an associated setter method
633633
member HasSetterMethod : bool
634634

635635
/// Get an associated setter method of the property
636636
member SetterMethod : FSharpMemberOrFunctionOrValue
637637

638+
/// Get an associated add method of an event
639+
member EventAddMethod : FSharpMemberOrFunctionOrValue
640+
641+
/// Get an associated remove method of an event
642+
member EventRemoveMethod : FSharpMemberOrFunctionOrValue
643+
644+
/// Get an associated delegate type of an event
645+
member EventDelegateType : FSharpType
646+
647+
/// Indicate if an event can be considered to be a property for the F# type system of type IEvent or IDelegateEvent.
648+
/// In this case ReturnParameter will have a type corresponding to the property type. For
649+
/// non-standard events, ReturnParameter will have a type corresponding to the delegate type.
650+
member EventIsStandard: bool
651+
638652
/// Indicates if this is an event member
639653
member IsEvent : bool
640654

src/fsharp/vs/service.fs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1473,7 +1473,7 @@ type TypeCheckInfo
14731473

14741474
member scope.GetReferencedAssemblies() =
14751475
[ for x in tcImports.GetImportedAssemblies() do
1476-
yield FSharpAssembly(g, thisCcu, tcImports, x.FSharpViewOfMetadata) ]
1476+
yield FSharpAssembly(g, tcImports, x.FSharpViewOfMetadata) ]
14771477

14781478
// Not, this does not have to be a SyncOp, it can be called from any thread
14791479
member scope.GetFormatSpecifierLocations() =
@@ -1928,7 +1928,7 @@ type FSharpCheckProjectResults(keepAssemblyContents, errors: FSharpErrorInfo[],
19281928
let (tcGlobals, tcImports, thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, ad, _tcAssemblyExpr) = getDetails()
19291929
let assemblies =
19301930
[ for x in tcImports.GetImportedAssemblies() do
1931-
yield FSharpAssembly(tcGlobals, thisCcu, tcImports, x.FSharpViewOfMetadata) ]
1931+
yield FSharpAssembly(tcGlobals, tcImports, x.FSharpViewOfMetadata) ]
19321932
FSharpProjectContext(thisCcu, assemblies, ad)
19331933

19341934
member info.RawFSharpAssemblyData =

tests/service/CSharpProjectAnalysis.fs

+27-25
Original file line numberDiff line numberDiff line change
@@ -65,33 +65,35 @@ let ``Test that csharp references are recognized as such`` () =
6565
let csharpAssembly = typeof<CSharpClass>.Assembly.Location
6666
let _, table = getProjectReferences("""module M""", [csharpAssembly], None, None)
6767
let ass = table.["CSharp_Analysis"]
68-
match ass.Contents.Entities |> Seq.tryFind (fun e -> e.DisplayName = "CSharpClass") with
69-
| Some found ->
70-
// this is no F# thing
71-
found.IsFSharp |> shouldEqual false
68+
let search = ass.Contents.Entities |> Seq.tryFind (fun e -> e.DisplayName = "CSharpClass")
69+
Assert.True search.IsSome
70+
let found = search.Value
71+
// this is no F# thing
72+
found.IsFSharp |> shouldEqual false
7273

73-
// Check that we have members
74-
let members = found.MembersFunctionsAndValues |> Seq.map (fun e -> e.CompiledName, e) |> dict
75-
members.ContainsKey ".ctor" |> shouldEqual true
76-
members.ContainsKey "Method" |> shouldEqual true
77-
members.ContainsKey "Property" |> shouldEqual true
78-
members.ContainsKey "Event" |> shouldEqual true
79-
members.ContainsKey "InterfaceMethod" |> shouldEqual true
80-
members.ContainsKey "InterfaceProperty" |> shouldEqual true
81-
members.ContainsKey "InterfaceEvent" |> shouldEqual true
74+
// Check that we have members
75+
let members = found.MembersFunctionsAndValues |> Seq.map (fun e -> e.CompiledName, e) |> dict
76+
members.ContainsKey ".ctor" |> shouldEqual true
77+
members.ContainsKey "Method" |> shouldEqual true
78+
members.ContainsKey "Property" |> shouldEqual true
79+
members.ContainsKey "Event" |> shouldEqual true
80+
members.ContainsKey "InterfaceMethod" |> shouldEqual true
81+
members.ContainsKey "InterfaceProperty" |> shouldEqual true
82+
members.ContainsKey "InterfaceEvent" |> shouldEqual true
83+
members.["Event"].IsEvent |> shouldEqual true
84+
members.["Event"].EventIsStandard |> shouldEqual true
85+
members.["Event"].EventAddMethod.DisplayName |> shouldEqual "add_Event"
86+
members.["Event"].EventRemoveMethod.DisplayName |> shouldEqual "remove_Event"
87+
members.["Event"].EventDelegateType.ToString() |> shouldEqual "type System.EventHandler"
8288

83-
//// Check that we get xml docs
84-
//String.IsNullOrWhiteSpace(members.[".ctor"].XmlDocSig) |> shouldEqual false
85-
//String.IsNullOrWhiteSpace(members.["Method"].XmlDocSig) |> shouldEqual false
86-
//String.IsNullOrWhiteSpace(members.["Property"].XmlDocSig) |> shouldEqual false
87-
//String.IsNullOrWhiteSpace(members.["Event"].XmlDocSig) |> shouldEqual false
88-
//String.IsNullOrWhiteSpace(members.["InterfaceMethod"].XmlDocSig) |> shouldEqual false
89-
//String.IsNullOrWhiteSpace(members.["InterfaceProperty"].XmlDocSig) |> shouldEqual false
90-
//String.IsNullOrWhiteSpace(members.["InterfaceEvent"].XmlDocSig) |> shouldEqual false
91-
92-
()
93-
| None ->
94-
Assert.Fail ("CSharpClass was not found in CSharp_Analysis assembly!")
89+
//// Check that we get xml docs
90+
members.[".ctor"].XmlDocSig |> shouldEqual "M:FSharp.Compiler.Service.Tests.CSharpClass.#ctor(System.Int32,System.String)"
91+
members.["Method"].XmlDocSig |> shouldEqual "M:FSharp.Compiler.Service.Tests.CSharpClass.Method(System.String)"
92+
members.["Property"].XmlDocSig |> shouldEqual "P:FSharp.Compiler.Service.Tests.CSharpClass.Property"
93+
members.["Event"].XmlDocSig |> shouldEqual "E:FSharp.Compiler.Service.Tests.CSharpClass.Event"
94+
members.["InterfaceMethod"].XmlDocSig |> shouldEqual "M:FSharp.Compiler.Service.Tests.CSharpClass.InterfaceMethod(System.String)"
95+
members.["InterfaceProperty"].XmlDocSig |> shouldEqual "P:FSharp.Compiler.Service.Tests.CSharpClass.InterfaceProperty"
96+
members.["InterfaceEvent"].XmlDocSig |> shouldEqual "E:FSharp.Compiler.Service.Tests.CSharpClass.InterfaceEvent"
9597

9698
[<Test>]
9799
let ``Test that symbols of csharp inner classes/enums are reported`` () =

0 commit comments

Comments
 (0)