From 83bbff8903804838941a736a5ea16847a2809154 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 13 Oct 2015 22:43:27 +0100 Subject: [PATCH 1/4] Fix 427 --- src/fsharp/vs/Symbols.fs | 37 ++++++++++++++++----------- src/fsharp/vs/Symbols.fsi | 7 +++++ tests/service/ProjectAnalysisTests.fs | 1 + 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/fsharp/vs/Symbols.fs b/src/fsharp/vs/Symbols.fs index 2044a10d30..b1c042ea45 100644 --- a/src/fsharp/vs/Symbols.fs +++ b/src/fsharp/vs/Symbols.fs @@ -1127,6 +1127,9 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = let nm = (match v with VRefNonLocal n -> n.ItemKey.PartialKey.LogicalName | _ -> "") 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])) @@ -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 = @@ -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() @@ -1328,6 +1321,20 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = | E _ -> true | _ -> false + member x.EventForFSharpProperty = + match d with + | P p when p.IsFSharpEventProperty && p.PropertyName.StartsWith "get_" -> + let nm = p.PropertyName.[4..] + let minfos1 = GetImmediateIntrinsicMethInfosOfType (Some("add_"+nm),AccessibleFromSomeFSharpCode) cenv.g cenv.amap range0 p.EnclosingType + let minfos2 = GetImmediateIntrinsicMethInfosOfType (Some("remove_"+nm),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 diff --git a/src/fsharp/vs/Symbols.fsi b/src/fsharp/vs/Symbols.fsi index ae4cae2962..a86c7d9746 100644 --- a/src/fsharp/vs/Symbols.fsi +++ b/src/fsharp/vs/Symbols.fsi @@ -697,6 +697,13 @@ and [] 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 diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index b49671259c..e64ec3dee0 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -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" From 29f04f7b94e3a14ce946c15b5a565f7482c3b1e0 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 13 Oct 2015 22:47:49 +0100 Subject: [PATCH 2/4] Fix 427 (correction) --- src/fsharp/vs/Symbols.fs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/fsharp/vs/Symbols.fs b/src/fsharp/vs/Symbols.fs index b1c042ea45..b656529617 100644 --- a/src/fsharp/vs/Symbols.fs +++ b/src/fsharp/vs/Symbols.fs @@ -1323,10 +1323,9 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = member x.EventForFSharpProperty = match d with - | P p when p.IsFSharpEventProperty && p.PropertyName.StartsWith "get_" -> - let nm = p.PropertyName.[4..] - let minfos1 = GetImmediateIntrinsicMethInfosOfType (Some("add_"+nm),AccessibleFromSomeFSharpCode) cenv.g cenv.amap range0 p.EnclosingType - let minfos2 = GetImmediateIntrinsicMethInfosOfType (Some("remove_"+nm),AccessibleFromSomeFSharpCode) cenv.g cenv.amap range0 p.EnclosingType + | 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 From 336ad148b9f7c2945f64e04f73ac5ab321dfb073 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 13 Oct 2015 23:01:17 +0100 Subject: [PATCH 3/4] Fix 427 (tests) --- tests/service/ProjectAnalysisTests.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index e64ec3dee0..87a8aaf7c4 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -1044,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"]); @@ -1055,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"]); @@ -1091,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"]); @@ -1101,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"])] [] let ``Test project3 all uses of all signature symbols`` () = From b61fa83a627c4428676a8ed18406d0ed03c959ab Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 13 Oct 2015 23:04:51 +0100 Subject: [PATCH 4/4] Fix 427 (tests 2) --- tests/service/ProjectAnalysisTests.fs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 87a8aaf7c4..06c68777ff 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -1172,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"]); @@ -1220,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"]); @@ -1318,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", @@ -1338,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