From d500d5212cc11ae2b7f5d089093fe561ca6d8010 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Mon, 31 Jul 2017 14:33:28 -0700 Subject: [PATCH] Expose receiver for static event assignemt --- .../Operations/CSharpOperationFactory.cs | 2 +- ...erationTests_IEventAssignmentExpression.cs | 43 +++++++++++++++++++ .../Operations/VisualBasicOperationFactory.vb | 6 +-- ...erationTests_IEventAssignmentExpression.vb | 34 +++++++++++++++ 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index ba48ce10a90..33fd7d2a4f6 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -365,7 +365,7 @@ private IEventAssignmentExpression CreateBoundEventAssignmentOperatorOperation(B // 2. the constant value of BoundEventAccess is always null. // 3. the syntax of the boundEventAssignmentOperator is always AssignmentExpressionSyntax, so the syntax for the event reference would be the LHS of the assignment. IEventSymbol @event = boundEventAssignmentOperator.Event; - Lazy instance = new Lazy(() => Create(boundEventAssignmentOperator.Event.IsStatic ? null : boundEventAssignmentOperator.ReceiverOpt)); + Lazy instance = new Lazy(() => Create(boundEventAssignmentOperator.ReceiverOpt)); SyntaxNode eventAccessSyntax = ((AssignmentExpressionSyntax)syntax).Left; return new LazyEventReferenceExpression(@event, instance, @event, eventAccessSyntax, @event.Type, ConvertToOptional(null)); diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.cs index c09a64b2463..ded5831b5f2 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.cs @@ -203,5 +203,48 @@ void M() VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } + + [Fact] + public void AddEventHandler_AssignToStaticEventOnInstance() + { + string source = @" +using System; + +class Test +{ + public static event EventHandler MyEvent; +} + +class C +{ + void Handler(object sender, EventArgs e) + { + } + + void M() + { + var t = new Test(); + /**/t.MyEvent += Handler/**/; + } +} +"; + string expectedOperationTree = @" +IEventAssignmentExpression (EventAdd)) (OperationKind.EventAssignmentExpression, Type: System.Void, IsInvalid) (Syntax: 't.MyEvent += Handler') + Event Reference: IEventReferenceExpression: event System.EventHandler Test.MyEvent (OperationKind.EventReferenceExpression, Type: System.EventHandler, IsInvalid) (Syntax: 't.MyEvent') + Instance Receiver: ILocalReferenceExpression: t (OperationKind.LocalReferenceExpression, Type: Test, IsInvalid) (Syntax: 't') + Handler: IMethodBindingExpression: void C.Handler(System.Object sender, System.EventArgs e) (OperationKind.MethodBindingExpression, Type: System.EventHandler) (Syntax: 'Handler') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: 'Handler') +"; + var expectedDiagnostics = new[] { + // file.cs(18,19): error CS0176: Member 'Test.MyEvent' cannot be accessed with an instance reference; qualify it with a type name instead + // /**/t.MyEvent += Handler/**/; + Diagnostic(ErrorCode.ERR_ObjectProhibited, "t.MyEvent").WithArguments("Test.MyEvent").WithLocation(18, 19), + // file.cs(6,38): warning CS0067: The event 'Test.MyEvent' is never used + // public static event EventHandler MyEvent; + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "MyEvent").WithArguments("Test.MyEvent").WithLocation(6, 38) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } } } diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 082d4b415f8..ebc5cd60c9c 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -574,11 +574,7 @@ Namespace Microsoft.CodeAnalysis.Semantics Private Function CreateBoundEventAccessOperation(boundEventAccess As BoundEventAccess) As IEventReferenceExpression Dim instance As Lazy(Of IOperation) = New Lazy(Of IOperation)( Function() - If boundEventAccess.EventSymbol.IsShared Then - Return Nothing - Else - Return Create(boundEventAccess.ReceiverOpt) - End If + Return Create(boundEventAccess.ReceiverOpt) End Function) Dim [event] As IEventSymbol = boundEventAccess.EventSymbol diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.vb index 3ae0ea6ddd0..2b1f9776f1f 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IEventAssignmentExpression.vb @@ -169,5 +169,39 @@ BC31143: Method 'Public Sub M(x As Integer)' does not have a signature compatibl VerifyOperationTreeAndDiagnosticsForTest(Of AddRemoveHandlerStatementSyntax)(source, expectedOperationTree, expectedDiagnostics) End Sub + + Public Sub AddEventHandler_AssignToSharedEventOnInstance() + Dim source = .Value + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = .Value + VerifyOperationTreeAndDiagnosticsForTest(Of AddRemoveHandlerStatementSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + End Class End Namespace -- GitLab