Skip to content

Commit

Permalink
Merge pull request #439 from dsyme/fix-427
Browse files Browse the repository at this point in the history
Fix 427 - Make event information for F#-declared CLIEvents available
  • Loading branch information
dsyme committed Oct 13, 2015
2 parents e0dc236 + b61fa83 commit 9be1780
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 27 deletions.
36 changes: 21 additions & 15 deletions src/fsharp/vs/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,9 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
let nm = (match v with VRefNonLocal n -> n.ItemKey.PartialKey.LogicalName | _ -> "<local>")
invalidOp (sprintf "The value or member '%s' does not exist or is in an unresolved assembly." nm)

let mkMethSym minfo = FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
let mkEventSym einfo = FSharpMemberOrFunctionOrValue(cenv, E einfo, Item.Event einfo)

new (cenv, vref) = FSharpMemberFunctionOrValue(cenv, V vref, Item.Value vref)
new (cenv, minfo) = FSharpMemberFunctionOrValue(cenv, M minfo, Item.MethodGroup(minfo.LogicalName, [minfo]))

Expand Down Expand Up @@ -1209,25 +1212,19 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
member __.GetterMethod =
checkIsResolved()
match d with
| P m ->
let minfo = m.GetterMethod
FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
| P m -> mkMethSym m.GetterMethod
| E _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated getter method"

member __.EventAddMethod =
checkIsResolved()
match d with
| E e ->
let minfo = e.GetAddMethod()
FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
| E e -> mkMethSym (e.GetAddMethod())
| P _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated add method"

member __.EventRemoveMethod =
checkIsResolved()
match d with
| E e ->
let minfo = e.GetRemoveMethod()
FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
| E e -> mkMethSym (e.GetRemoveMethod())
| P _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated remove method"

member __.EventDelegateType =
Expand Down Expand Up @@ -1256,12 +1253,8 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
member __.SetterMethod =
checkIsResolved()
match d with
| P m ->
let minfo = m.SetterMethod
FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName,[minfo]))
| E _
| M _
| V _ -> invalidOp "the value or member doesn't have an associated setter method"
| P m -> mkMethSym m.SetterMethod
| E _ | M _ | V _ -> invalidOp "the value or member doesn't have an associated setter method"

member __.EnclosingEntity =
checkIsResolved()
Expand Down Expand Up @@ -1328,6 +1321,19 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
| E _ -> true
| _ -> false

member x.EventForFSharpProperty =
match d with
| P p when p.IsFSharpEventProperty ->
let minfos1 = GetImmediateIntrinsicMethInfosOfType (Some("add_"+p.PropertyName),AccessibleFromSomeFSharpCode) cenv.g cenv.amap range0 p.EnclosingType
let minfos2 = GetImmediateIntrinsicMethInfosOfType (Some("remove_"+p.PropertyName),AccessibleFromSomeFSharpCode) cenv.g cenv.amap range0 p.EnclosingType
match minfos1,minfos2 with
| [addMeth],[removeMeth] ->
match addMeth.ArbitraryValRef, removeMeth.ArbitraryValRef with
| Some addVal, Some removeVal -> Some (mkEventSym (FSEvent(cenv.g, p, addVal, removeVal)))
| _ -> None
| _ -> None
| _ -> None

member __.IsEventAddMethod =
if isUnresolved() then false else
match d with
Expand Down
7 changes: 7 additions & 0 deletions src/fsharp/vs/Symbols.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,13 @@ and [<Class>] FSharpMemberOrFunctionOrValue =
/// Indicates if this is an event member
member IsEvent : bool

/// Gets the event symbol implied by the use of a property,
/// for the case where the property is actually an F#-declared CLIEvent.
///
/// Uses of F#-declared events are considered to be properties as far as the language specification
/// and this API are concerned.
member EventForFSharpProperty : FSharpMemberOrFunctionOrValue option

/// Indicates if this is an abstract member?
member IsDispatchSlot : bool

Expand Down
25 changes: 13 additions & 12 deletions tests/service/ProjectAnalysisTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ let attribsOfSymbol (s:FSharpSymbol) =
if v.IsPropertyGetterMethod then yield "getter"
if v.IsPropertySetterMethod then yield "setter"
if v.IsEvent then yield "event"
if v.EventForFSharpProperty.IsSome then yield "clievent"
if v.IsEventAddMethod then yield "add"
if v.IsEventRemoveMethod then yield "remove"
if v.IsTypeFunction then yield "typefun"
Expand Down Expand Up @@ -1043,7 +1044,7 @@ let ``Test project3 all symbols in signature`` () =
("member set_InterfacePropertySet", ["slot"; "member"; "setter"]);
("property InterfacePropertySet", ["slot"; "member"; "prop"]);
("property InterfaceProperty", ["slot"; "member"; "prop"]);
("property InterfaceEvent", ["slot"; "member"; "prop"]);
("property InterfaceEvent", ["slot"; "member"; "prop"; "clievent"]);
("CFoo", ["class"]);
("member .ctor", ["member"; "ctor"]);
("member AbstractClassMethod", ["slot"; "member"]);
Expand All @@ -1054,7 +1055,7 @@ let ``Test project3 all symbols in signature`` () =
("member set_AbstractClassPropertySet", ["slot"; "member"; "setter"]);
("property AbstractClassPropertySet", ["slot"; "member"; "prop"]);
("property AbstractClassProperty", ["slot"; "member"; "prop"]);
("property AbstractClassEvent", ["slot"; "member"; "prop"]);
("property AbstractClassEvent", ["slot"; "member"; "prop"; "clievent"]);
("CBaseFoo", ["class"]); ("member .ctor", ["member"; "ctor"]);
("member BaseClassMethod", ["slot"; "member"]);
("member BaseClassMethod", ["member"; "overridemem"]);
Expand Down Expand Up @@ -1090,7 +1091,7 @@ let ``Test project3 all symbols in signature`` () =
("member set_AbstractClassPropertySet", ["member"; "setter"; "overridemem"]);
("property AbstractClassPropertySet", ["member"; "prop"; "overridemem"]);
("property AbstractClassProperty", ["member"; "prop"; "overridemem"]);
("property AbstractClassEvent", ["member"; "prop"; "overridemem"]);
("property AbstractClassEvent", ["member"; "prop"; "clievent"; "overridemem"]);
("CBaseFooImpl", ["class"]); ("member .ctor", ["member"; "ctor"]);
("member BaseClassMethod", ["member"; "overridemem"]);
("member add_BaseClassEvent", ["member"; "add"; "overridemem"]);
Expand All @@ -1100,7 +1101,7 @@ let ``Test project3 all symbols in signature`` () =
("member set_BaseClassPropertySet", ["member"; "setter"; "overridemem"]);
("property BaseClassPropertySet", ["member"; "prop"; "overridemem"]);
("property BaseClassProperty", ["member"; "prop"; "overridemem"]);
("property BaseClassEvent", ["member"; "prop"; "overridemem"])]
("property BaseClassEvent", ["member"; "prop"; "clievent"; "overridemem"])]

[<Test>]
let ``Test project3 all uses of all signature symbols`` () =
Expand Down Expand Up @@ -1171,9 +1172,9 @@ let ``Test project3 all uses of all signature symbols`` () =
("file1", ((76, 23), (76, 44)), [], ["slot"; "member"; "prop"]);
("file1", ((34, 20), (34, 37)), ["override"], ["slot"; "member"; "prop"])]);
("property InterfaceEvent",
[("file1", ((8, 13), (8, 27)), ["defn"], ["slot"; "member"; "prop"]);
("file1", ((65, 20), (65, 34)), ["override"], ["slot"; "member"; "prop"]);
("file1", ((38, 20), (38, 34)), ["override"], ["slot"; "member"; "prop"])]);
[("file1", ((8, 13), (8, 27)), ["defn"], ["slot"; "member"; "prop"; "clievent"]);
("file1", ((65, 20), (65, 34)), ["override"], ["slot"; "member"; "prop"; "clievent"]);
("file1", ((38, 20), (38, 34)), ["override"], ["slot"; "member"; "prop"; "clievent"])]);
("CFoo",
[("file1", ((11, 5), (11, 9)), ["defn"], ["class"]);
("file1", ((41, 12), (41, 16)), ["type"], ["class"]);
Expand Down Expand Up @@ -1219,9 +1220,9 @@ let ``Test project3 all uses of all signature symbols`` () =
("file1", ((70, 22), (70, 43)), ["override"], ["slot"; "member"; "prop"]);
("file1", ((43, 18), (43, 39)), ["override"], ["slot"; "member"; "prop"])]);
("property AbstractClassEvent",
[("file1", ((16, 13), (16, 31)), ["defn"], ["slot"; "member"; "prop"]);
("file1", ((74, 22), (74, 40)), ["override"], ["slot"; "member"; "prop"]);
("file1", ((47, 18), (47, 36)), ["override"], ["slot"; "member"; "prop"])]);
[("file1", ((16, 13), (16, 31)), ["defn"], ["slot"; "member"; "prop"; "clievent"]);
("file1", ((74, 22), (74, 40)), ["override"], ["slot"; "member"; "prop"; "clievent"]);
("file1", ((47, 18), (47, 36)), ["override"], ["slot"; "member"; "prop"; "clievent"])]);
("CBaseFoo",
[("file1", ((18, 5), (18, 13)), ["defn"], ["class"]);
("file1", ((50, 12), (50, 20)), ["type"], ["class"]);
Expand Down Expand Up @@ -1317,7 +1318,7 @@ let ``Test project3 all uses of all signature symbols`` () =
("property AbstractClassProperty",
[("file1", ((43, 18), (43, 39)), ["defn"], ["member"; "prop"; "overridemem"])]);
("property AbstractClassEvent",
[("file1", ((47, 18), (47, 36)), ["defn"], ["member"; "prop"; "overridemem"])]);
[("file1", ((47, 18), (47, 36)), ["defn"], ["member"; "prop"; "clievent"; "overridemem"])]);
("CBaseFooImpl", [("file1", ((49, 5), (49, 17)), ["defn"], ["class"])]);
("member .ctor", [("file1", ((49, 5), (49, 17)), ["defn"], ["member"; "ctor"])]);
("member BaseClassMethod",
Expand All @@ -1337,7 +1338,7 @@ let ``Test project3 all uses of all signature symbols`` () =
("property BaseClassProperty",
[("file1", ((52, 18), (52, 35)), ["defn"], ["member"; "prop"; "overridemem"])]);
("property BaseClassEvent",
[("file1", ((56, 18), (56, 32)), ["defn"], ["member"; "prop"; "overridemem"])])]
[("file1", ((56, 18), (56, 32)), ["defn"], ["member"; "prop"; "clievent"; "overridemem"])])]
set allUsesOfAllSymbols - set expected |> shouldEqual Set.empty
set expected - set allUsesOfAllSymbols |> shouldEqual Set.empty
(set expected = set allUsesOfAllSymbols) |> shouldEqual true
Expand Down

0 comments on commit 9be1780

Please sign in to comment.