提交 5aca5d78 编写于 作者: G Gen Lu

Fix IEventAssignmentExpression

上级 68e37cf1
......@@ -355,14 +355,26 @@ private IEventReferenceExpression CreateBoundEventAccessOperation(BoundEventAcce
private IEventAssignmentExpression CreateBoundEventAssignmentOperatorOperation(BoundEventAssignmentOperator boundEventAssignmentOperator)
{
IEventSymbol @event = boundEventAssignmentOperator.Event;
Lazy<IOperation> eventInstance = new Lazy<IOperation>(() => Create(boundEventAssignmentOperator.Event.IsStatic ? null : boundEventAssignmentOperator.ReceiverOpt));
SyntaxNode syntax = boundEventAssignmentOperator.Syntax;
Lazy<IEventReferenceExpression> eventReference = new Lazy<IEventReferenceExpression>(() =>
{
IEventSymbol @event = boundEventAssignmentOperator.Event;
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(boundEventAssignmentOperator.Event.IsStatic ? null : boundEventAssignmentOperator.ReceiverOpt));
ISymbol member = boundEventAssignmentOperator.Event;
// BoundEventAssignmentOperator doesn't hold on to all the data from the provided BoundEventAccess during binding.
// Based on the implementation of those two bound node types, the following data can be retieved w/o changing BoundEventAssignmentOperator:
// 1. The type of BoundEventAccess is the type of the event symbol.
// 2. the constant value of BoundEventAccess is always null.
// However, we can't reliably get the syntax node for the BoundEventAccess w/o changing BoundEventAssignmentOperator, so the syntax of entire
// BoundEventAssignmentOperator is used instead.
return new LazyEventReferenceExpression(@event, instance, @event, syntax, @event.Type, ConvertToOptional(null));
});
Lazy<IOperation> handlerValue = new Lazy<IOperation>(() => Create(boundEventAssignmentOperator.Argument));
bool adds = boundEventAssignmentOperator.IsAddition;
SyntaxNode syntax = boundEventAssignmentOperator.Syntax;
ITypeSymbol type = boundEventAssignmentOperator.Type;
Optional<object> constantValue = ConvertToOptional(boundEventAssignmentOperator.ConstantValue);
return new LazyEventAssignmentExpression(@event, eventInstance, handlerValue, adds, syntax, type, constantValue);
return new LazyEventAssignmentExpression(eventReference, handlerValue, adds, syntax, type, constantValue);
}
private IParameterReferenceExpression CreateBoundParameterOperation(BoundParameter boundParameter)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class IOperationTests : SemanticModelTestBase
{
[Fact]
public void AddEventHandler()
{
string source = @"
using System;
class Test
{
public event EventHandler MyEvent;
}
class C
{
void Handler(object sender, EventArgs e)
{
}
void M()
{
var t = new Test();
/*<bind>*/t.MyEvent += Handler/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IEventAssignmentExpression (EventAdd)) (OperationKind.EventAssignmentExpression, Type: System.Void) (Syntax: 't.MyEvent += Handler')
Event Reference: IEventReferenceExpression: event System.EventHandler Test.MyEvent (OperationKind.EventReferenceExpression, Type: System.EventHandler) (Syntax: 't.MyEvent += Handler')
Instance Receiver: ILocalReferenceExpression: t (OperationKind.LocalReferenceExpression, Type: Test) (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(6,31): warning CS0067: The event 'Test.MyEvent' is never used
// public event EventHandler MyEvent;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "MyEvent").WithArguments("Test.MyEvent").WithLocation(6, 31)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void RemoveEventHandler()
{
string source = @"
using System;
class Test
{
public event EventHandler MyEvent;
}
class C
{
void M()
{
var t = new Test();
/*<bind>*/t.MyEvent -= null/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IEventAssignmentExpression (EventRemove)) (OperationKind.EventAssignmentExpression, Type: System.Void) (Syntax: 't.MyEvent -= null')
Event Reference: IEventReferenceExpression: event System.EventHandler Test.MyEvent (OperationKind.EventReferenceExpression, Type: System.EventHandler) (Syntax: 't.MyEvent -= null')
Instance Receiver: ILocalReferenceExpression: t (OperationKind.LocalReferenceExpression, Type: Test) (Syntax: 't')
Handler: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.EventHandler, Constant: null) (Syntax: 'null')
ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null')
";
var expectedDiagnostics = new[] {
// file.cs(6,31): warning CS0067: The event 'Test.MyEvent' is never used
// public event EventHandler MyEvent;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "MyEvent").WithArguments("Test.MyEvent").WithLocation(6, 31)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void AddEventHandler_StaticEvent()
{
string source = @"
using System;
class Test
{
public static event EventHandler MyEvent;
}
class C
{
void Handler(object sender, EventArgs e)
{
}
void M()
{
/*<bind>*/Test.MyEvent += Handler/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IEventAssignmentExpression (EventAdd)) (OperationKind.EventAssignmentExpression, Type: System.Void) (Syntax: 'Test.MyEvent += Handler')
Event Reference: IEventReferenceExpression: event System.EventHandler Test.MyEvent (Static) (OperationKind.EventReferenceExpression, Type: System.EventHandler) (Syntax: 'Test.MyEvent += Handler')
Instance Receiver: null
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(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<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void RemoveEventHandler_StaticEvent()
{
string source = @"
using System;
class Test
{
public static event EventHandler MyEvent;
}
class C
{
void Handler(object sender, EventArgs e)
{
}
void M()
{
/*<bind>*/Test.MyEvent -= Handler/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IEventAssignmentExpression (EventRemove)) (OperationKind.EventAssignmentExpression, Type: System.Void) (Syntax: 'Test.MyEvent -= Handler')
Event Reference: IEventReferenceExpression: event System.EventHandler Test.MyEvent (Static) (OperationKind.EventReferenceExpression, Type: System.EventHandler) (Syntax: 'Test.MyEvent -= Handler')
Instance Receiver: null
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(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<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void AddEventHandler_DelegateTypeMismatch()
{
string source = @"
using System;
class Test
{
public event EventHandler MyEvent;
}
class C
{
void Handler(object sender)
{
}
void M()
{
var t = new Test();
/*<bind>*/t.MyEvent += Handler/*<bind>*/;
}
}
";
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 += Handler')
Instance Receiver: ILocalReferenceExpression: t (OperationKind.LocalReferenceExpression, Type: Test, IsInvalid) (Syntax: 't')
Handler: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.EventHandler, IsInvalid) (Syntax: 'Handler')
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'Handler')
";
var expectedDiagnostics = new[] {
// file.cs(18,19): error CS0123: No overload for 'Handler' matches delegate 'EventHandler'
// /*<bind>*/t.MyEvent += Handler/*<bind>*/;
Diagnostic(ErrorCode.ERR_MethDelegateMismatch, "t.MyEvent += Handler").WithArguments("Handler", "System.EventHandler").WithLocation(18, 19),
// file.cs(6,31): warning CS0067: The event 'Test.MyEvent' is never used
// public event EventHandler MyEvent;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "MyEvent").WithArguments("Test.MyEvent").WithLocation(6, 31)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
......@@ -1458,21 +1458,16 @@ public override void Accept(OperationVisitor visitor)
/// </summary>
internal abstract partial class BaseEventAssignmentExpression : Operation, IEventAssignmentExpression
{
protected BaseEventAssignmentExpression(IEventSymbol @event, bool adds, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
protected BaseEventAssignmentExpression(bool adds, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(OperationKind.EventAssignmentExpression, syntax, type, constantValue)
{
Event = @event;
Adds = adds;
}
/// <summary>
/// Event being bound.
/// </summary>
public IEventSymbol Event { get; }
/// <summary>
/// Instance used to refer to the event being bound.
/// Reference to the event being bound.
/// </summary>
public abstract IOperation EventInstance { get; }
public abstract IEventReferenceExpression EventReference { get; }
/// <summary>
/// Handler supplied for the event.
......@@ -1487,7 +1482,7 @@ public override IEnumerable<IOperation> Children
{
get
{
yield return EventInstance;
yield return EventReference;
yield return HandlerValue;
}
}
......@@ -1506,17 +1501,17 @@ public override void Accept(OperationVisitor visitor)
/// </summary>
internal sealed partial class EventAssignmentExpression : BaseEventAssignmentExpression, IEventAssignmentExpression
{
public EventAssignmentExpression(IEventSymbol @event, IOperation eventInstance, IOperation handlerValue, bool adds, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(@event, adds, syntax, type, constantValue)
public EventAssignmentExpression(IEventReferenceExpression eventReference, IOperation handlerValue, bool adds, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(adds, syntax, type, constantValue)
{
EventInstance = eventInstance;
EventReference = eventReference;
HandlerValue = handlerValue;
}
/// <summary>
/// Instance used to refer to the event being bound.
/// </summary>
public override IOperation EventInstance { get; }
public override IEventReferenceExpression EventReference { get; }
/// <summary>
/// Handler supplied for the event.
......@@ -1529,19 +1524,19 @@ internal sealed partial class EventAssignmentExpression : BaseEventAssignmentExp
/// </summary>
internal sealed partial class LazyEventAssignmentExpression : BaseEventAssignmentExpression, IEventAssignmentExpression
{
private readonly Lazy<IOperation> _lazyEventInstance;
private readonly Lazy<IEventReferenceExpression> _lazyEventReference;
private readonly Lazy<IOperation> _lazyHandlerValue;
public LazyEventAssignmentExpression(IEventSymbol @event, Lazy<IOperation> eventInstance, Lazy<IOperation> handlerValue, bool adds, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) : base(@event, adds, syntax, type, constantValue)
public LazyEventAssignmentExpression(Lazy<IEventReferenceExpression> eventReference, Lazy<IOperation> handlerValue, bool adds, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) : base(adds, syntax, type, constantValue)
{
_lazyEventInstance = eventInstance ?? throw new System.ArgumentNullException(nameof(eventInstance));
_lazyEventReference = eventReference ?? throw new System.ArgumentNullException(nameof(eventReference));
_lazyHandlerValue = handlerValue ?? throw new System.ArgumentNullException(nameof(handlerValue));
}
/// <summary>
/// Instance used to refer to the event being bound.
/// </summary>
public override IOperation EventInstance => _lazyEventInstance.Value;
public override IEventReferenceExpression EventReference => _lazyEventReference.Value;
/// <summary>
/// Handler supplied for the event.
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.Semantics
{
/// <summary>
......@@ -14,15 +12,10 @@ namespace Microsoft.CodeAnalysis.Semantics
public interface IEventAssignmentExpression : IOperation
{
/// <summary>
/// Event being bound.
/// Reference to the event being bound.
/// </summary>
IEventSymbol Event { get; }
/// <summary>
/// Instance used to refer to the event being bound.
/// </summary>
IOperation EventInstance { get; }
IEventReferenceExpression EventReference { get; }
/// <summary>
/// Handler supplied for the event.
/// </summary>
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.Semantics
{
/// <summary>
......
......@@ -405,8 +405,7 @@ Microsoft.CodeAnalysis.Semantics.IEmptyStatement
Microsoft.CodeAnalysis.Semantics.IEndStatement
Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression
Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression.Adds.get -> bool
Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression.Event.get -> Microsoft.CodeAnalysis.IEventSymbol
Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression.EventInstance.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression.EventReference.get -> Microsoft.CodeAnalysis.Semantics.IEventReferenceExpression
Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression.HandlerValue.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Semantics.IEventReferenceExpression
Microsoft.CodeAnalysis.Semantics.IEventReferenceExpression.Event.get -> Microsoft.CodeAnalysis.IEventSymbol
......
......@@ -408,20 +408,16 @@ Namespace Microsoft.CodeAnalysis.Semantics
Private Function GetAddHandlerStatementExpression(statement As BoundAddHandlerStatement) As IOperation
Dim eventAccess As BoundEventAccess = TryCast(statement.EventAccess, BoundEventAccess)
Dim [event] As IEventSymbol = eventAccess?.EventSymbol
Dim instance = If([event] Is Nothing OrElse [event].IsStatic, Nothing, If(eventAccess IsNot Nothing, Create(eventAccess.ReceiverOpt), Nothing))
Dim eventReference = If(eventAccess Is Nothing, Nothing, CreateBoundEventAccessOperation(eventAccess))
Return New EventAssignmentExpression(
[event], instance, Create(statement.Handler), adds:=True, syntax:=statement.Syntax, type:=Nothing, constantValue:=Nothing)
eventReference, Create(statement.Handler), adds:=True, syntax:=statement.Syntax, type:=Nothing, constantValue:=Nothing)
End Function
Private Function GetRemoveStatementExpression(statement As BoundRemoveHandlerStatement) As IOperation
Dim eventAccess As BoundEventAccess = TryCast(statement.EventAccess, BoundEventAccess)
Dim [event] As IEventSymbol = eventAccess?.EventSymbol
Dim instance = If([event] Is Nothing OrElse [event].IsStatic, Nothing, If(eventAccess IsNot Nothing, Create(eventAccess.ReceiverOpt), Nothing))
Dim eventReference = If(eventAccess Is Nothing, Nothing, CreateBoundEventAccessOperation(eventAccess))
Return New EventAssignmentExpression(
[event], instance, Create(statement.Handler), adds:=False, syntax:=statement.Syntax, type:=Nothing, constantValue:=Nothing)
eventReference, Create(statement.Handler), adds:=False, syntax:=statement.Syntax, type:=Nothing, constantValue:=Nothing)
End Function
Private Shared Function GetConversionKind(kind As VisualBasic.ConversionKind) As Semantics.ConversionKind
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
Inherits SemanticModelTestBase
<Fact>
Public Sub AddEventHandler()
Dim source = <![CDATA[
Imports System
Class TestClass
Event TestEvent As Action
Sub Add(receiver As TestClass)
AddHandler TestEvent, AddressOf M'BIND:"AddHandler TestEvent, AddressOf M"
End Sub
Sub M()
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'AddHandler ... AddressOf M')
IEventAssignmentExpression (EventAdd)) (OperationKind.EventAssignmentExpression, Type: null) (Syntax: 'AddHandler ... AddressOf M')
Event Reference: IEventReferenceExpression: Event TestClass.TestEvent As System.Action (OperationKind.EventReferenceExpression, Type: System.Action) (Syntax: 'TestEvent')
Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: TestClass) (Syntax: 'TestEvent')
Handler: IOperation: (OperationKind.None) (Syntax: 'AddressOf M')
Children(1):
IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: TestClass) (Syntax: 'M')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AddRemoveHandlerStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact>
Public Sub RemoveEventHandler()
Dim source = <![CDATA[
Imports System
Class TestClass
Event TestEvent As Action
Sub Remove(receiver As TestClass)
RemoveHandler TestEvent, AddressOf M'BIND:"RemoveHandler TestEvent, AddressOf M"
End Sub
Sub M()
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'RemoveHandl ... AddressOf M')
IEventAssignmentExpression (EventRemove)) (OperationKind.EventAssignmentExpression, Type: null) (Syntax: 'RemoveHandl ... AddressOf M')
Event Reference: IEventReferenceExpression: Event TestClass.TestEvent As System.Action (OperationKind.EventReferenceExpression, Type: System.Action) (Syntax: 'TestEvent')
Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: TestClass) (Syntax: 'TestEvent')
Handler: IOperation: (OperationKind.None) (Syntax: 'AddressOf M')
Children(1):
IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: TestClass) (Syntax: 'M')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AddRemoveHandlerStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact>
Public Sub AddEventHandler_StaticEvent()
Dim source = <![CDATA[
Imports System
Class TestClass
Shared Event TestEvent As Action
Sub Add(receiver As TestClass)
AddHandler TestEvent, AddressOf M'BIND:"AddHandler TestEvent, AddressOf M"
End Sub
Sub M()
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'AddHandler ... AddressOf M')
IEventAssignmentExpression (EventAdd)) (OperationKind.EventAssignmentExpression, Type: null) (Syntax: 'AddHandler ... AddressOf M')
Event Reference: IEventReferenceExpression: Event TestClass.TestEvent As System.Action (Static) (OperationKind.EventReferenceExpression, Type: System.Action) (Syntax: 'TestEvent')
Instance Receiver: null
Handler: IOperation: (OperationKind.None) (Syntax: 'AddressOf M')
Children(1):
IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: TestClass) (Syntax: 'M')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AddRemoveHandlerStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact>
Public Sub RemoveEventHandler_StaticEvent()
Dim source = <![CDATA[
Imports System
Class TestClass
Shared Event TestEvent As Action
Sub Remove(receiver As TestClass)
RemoveHandler TestEvent, AddressOf M'BIND:"RemoveHandler TestEvent, AddressOf M"
End Sub
Sub M()
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'RemoveHandl ... AddressOf M')
IEventAssignmentExpression (EventRemove)) (OperationKind.EventAssignmentExpression, Type: null) (Syntax: 'RemoveHandl ... AddressOf M')
Event Reference: IEventReferenceExpression: Event TestClass.TestEvent As System.Action (Static) (OperationKind.EventReferenceExpression, Type: System.Action) (Syntax: 'TestEvent')
Instance Receiver: null
Handler: IOperation: (OperationKind.None) (Syntax: 'AddressOf M')
Children(1):
IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: TestClass) (Syntax: 'M')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AddRemoveHandlerStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact>
Public Sub RemoveEventHandler_DelegateTypeMismatch()
Dim source = <![CDATA[
Imports System
Class TestClass
Shared Event TestEvent As Action
Sub Remove(receiver As TestClass)
RemoveHandler TestEvent, AddressOf M'BIND:"RemoveHandler TestEvent, AddressOf M"
End Sub
Sub M(x as Integer)
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: 'RemoveHandl ... AddressOf M')
IEventAssignmentExpression (EventRemove)) (OperationKind.EventAssignmentExpression, Type: null, IsInvalid) (Syntax: 'RemoveHandl ... AddressOf M')
Event Reference: IEventReferenceExpression: Event TestClass.TestEvent As System.Action (Static) (OperationKind.EventReferenceExpression, Type: System.Action) (Syntax: 'TestEvent')
Instance Receiver: null
Handler: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: 'AddressOf M')
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'AddressOf M')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC31143: Method 'Public Sub M(x As Integer)' does not have a signature compatible with delegate 'Delegate Sub Action()'.
RemoveHandler TestEvent, AddressOf M'BIND:"RemoveHandler TestEvent, AddressOf M"
~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AddRemoveHandlerStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
......@@ -724,11 +724,10 @@ public override void VisitEventAssignmentExpression(IEventAssignmentExpression o
{
var kindStr = operation.Adds ? "EventAdd" : "EventRemove";
LogString($"{nameof(IEventAssignmentExpression)} ({kindStr})");
LogSymbol(operation.Event, header: " (Event: ");
LogString(")");
LogCommonPropertiesAndNewLine(operation);
Visit(operation.EventInstance, header: "Event Instance");
Visit(operation.EventReference, header: "Event Reference");
Visit(operation.HandlerValue, header: "Handler");
}
......
......@@ -302,7 +302,6 @@ public override void VisitEventReferenceExpression(IEventReferenceExpression ope
public override void VisitEventAssignmentExpression(IEventAssignmentExpression operation)
{
var eventSymbol = operation.Event;
var adds = operation.Adds;
base.VisitEventAssignmentExpression(operation);
......
......@@ -1060,9 +1060,9 @@ public sealed override void Initialize(AnalysisContext context)
IEventAssignmentExpression eventAssignment = (IEventAssignmentExpression)operationContext.Operation;
operationContext.ReportDiagnostic(Diagnostic.Create(eventAssignment.Adds ? HandlerAddedDescriptor : HandlerRemovedDescriptor, operationContext.Operation.Syntax.GetLocation()));
if (eventAssignment.Event == null)
if (eventAssignment.EventReference?.Event == null)
{
if (eventAssignment.EventInstance == null && eventAssignment.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
if (eventAssignment.EventReference?.Instance == null && eventAssignment.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
{
// report inside after checking for null to make sure it does't crash.
operationContext.ReportDiagnostic(Diagnostic.Create(InvalidEventDescriptor, eventAssignment.Syntax.GetLocation()));
......@@ -1425,10 +1425,6 @@ public sealed override void Initialize(AnalysisContext context)
memberSymbol = ((IInvocationExpression)operation).TargetMethod;
receiver = ((IInvocationExpression)operation).Instance;
break;
case OperationKind.EventAssignmentExpression:
memberSymbol = ((IEventAssignmentExpression)operation).Event;
receiver = ((IEventAssignmentExpression)operation).EventInstance;
break;
default:
throw new ArgumentException();
}
......@@ -1446,8 +1442,7 @@ public sealed override void Initialize(AnalysisContext context)
OperationKind.PropertyReferenceExpression,
OperationKind.EventReferenceExpression,
OperationKind.MethodBindingExpression,
OperationKind.InvocationExpression,
OperationKind.EventAssignmentExpression);
OperationKind.InvocationExpression);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册