提交 c3b3e9dc 编写于 作者: G Gen Lu

Merge pull request #8433 from genlu/fix8385_

Make `Instance` return 'null' when the referenced member is static
...@@ -40,7 +40,7 @@ partial class BoundCall : IInvocationExpression ...@@ -40,7 +40,7 @@ partial class BoundCall : IInvocationExpression
{ {
IMethodSymbol IInvocationExpression.TargetMethod => this.Method; IMethodSymbol IInvocationExpression.TargetMethod => this.Method;
IExpression IInvocationExpression.Instance => this.ReceiverOpt; IExpression IInvocationExpression.Instance => this.Method.IsStatic ? null : this.ReceiverOpt;
bool IInvocationExpression.IsVirtual => (this.Method.IsVirtual || this.Method.IsAbstract || this.Method.IsOverride) && !this.ReceiverOpt.SuppressVirtualCalls; bool IInvocationExpression.IsVirtual => (this.Method.IsVirtual || this.Method.IsAbstract || this.Method.IsOverride) && !this.ReceiverOpt.SuppressVirtualCalls;
...@@ -299,7 +299,7 @@ public override void Accept(OperationVisitor visitor) ...@@ -299,7 +299,7 @@ public override void Accept(OperationVisitor visitor)
partial class BoundFieldAccess : IFieldReferenceExpression partial class BoundFieldAccess : IFieldReferenceExpression
{ {
IExpression IMemberReferenceExpression.Instance => this.ReceiverOpt; IExpression IMemberReferenceExpression.Instance => this.FieldSymbol.IsStatic? null : this.ReceiverOpt;
ISymbol IMemberReferenceExpression.Member => this.FieldSymbol; ISymbol IMemberReferenceExpression.Member => this.FieldSymbol;
...@@ -322,7 +322,7 @@ partial class BoundPropertyAccess : IPropertyReferenceExpression ...@@ -322,7 +322,7 @@ partial class BoundPropertyAccess : IPropertyReferenceExpression
{ {
IPropertySymbol IPropertyReferenceExpression.Property => this.PropertySymbol; IPropertySymbol IPropertyReferenceExpression.Property => this.PropertySymbol;
IExpression IMemberReferenceExpression.Instance => this.ReceiverOpt; IExpression IMemberReferenceExpression.Instance => this.PropertySymbol.IsStatic ? null : this.ReceiverOpt;
ISymbol IMemberReferenceExpression.Member => this.PropertySymbol; ISymbol IMemberReferenceExpression.Member => this.PropertySymbol;
...@@ -343,7 +343,7 @@ partial class BoundEventAccess : IEventReferenceExpression ...@@ -343,7 +343,7 @@ partial class BoundEventAccess : IEventReferenceExpression
{ {
IEventSymbol IEventReferenceExpression.Event => this.EventSymbol; IEventSymbol IEventReferenceExpression.Event => this.EventSymbol;
IExpression IMemberReferenceExpression.Instance => this.ReceiverOpt; IExpression IMemberReferenceExpression.Instance => this.EventSymbol.IsStatic ? null : this.ReceiverOpt;
ISymbol IMemberReferenceExpression.Member => this.EventSymbol; ISymbol IMemberReferenceExpression.Member => this.EventSymbol;
...@@ -364,7 +364,7 @@ partial class BoundEventAssignmentOperator : IEventAssignmentExpression ...@@ -364,7 +364,7 @@ partial class BoundEventAssignmentOperator : IEventAssignmentExpression
{ {
IEventSymbol IEventAssignmentExpression.Event => this.Event; IEventSymbol IEventAssignmentExpression.Event => this.Event;
IExpression IEventAssignmentExpression.EventInstance => this.ReceiverOpt; IExpression IEventAssignmentExpression.EventInstance => this.Event.IsStatic ? null : this.ReceiverOpt;
IExpression IEventAssignmentExpression.HandlerValue => this.Argument; IExpression IEventAssignmentExpression.HandlerValue => this.Argument;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage; using Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage;
using Roslyn.Test.Utilities;
using Xunit; using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests namespace Microsoft.CodeAnalysis.CSharp.UnitTests
...@@ -1277,5 +1278,56 @@ public void OnMumble(System.EventArgs args) ...@@ -1277,5 +1278,56 @@ public void OnMumble(System.EventArgs args)
Diagnostic(LambdaTestAnalyzer.LambdaExpressionDescriptor.Id, "(s, e) => { int i = 0; i++; i++; i++; }").WithLocation(23, 19), Diagnostic(LambdaTestAnalyzer.LambdaExpressionDescriptor.Id, "(s, e) => { int i = 0; i++; i++; i++; }").WithLocation(23, 19),
Diagnostic(LambdaTestAnalyzer.TooManyStatementsInLambdaExpressionDescriptor.Id, "(s, e) => { int i = 0; i++; i++; i++; }").WithLocation(23, 19)); Diagnostic(LambdaTestAnalyzer.TooManyStatementsInLambdaExpressionDescriptor.Id, "(s, e) => { int i = 0; i++; i++; i++; }").WithLocation(23, 19));
} }
[WorkItem(8385, "https://github.com/dotnet/roslyn/issues/8385")]
[Fact]
public void StaticMemberReferenceCSharp()
{
const string source = @"
using System;
public class D
{
public static event Action E;
public static int Field;
public static int Property => 0;
public static void Method() { }
}
class C
{
public static event Action E;
public static void Bar() { }
void Foo()
{
C.E += D.Method;
C.E();
C.Bar();
D.E += () => { };
D.Field = 1;
var x = D.Property;
D.Method();
}
}
";
CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics(Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("D.E").WithLocation(6, 32))
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new StaticMemberTestAnalyzer() }, null, null, false,
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "C.E += D.Method").WithLocation(23, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.Method").WithLocation(23, 16),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "C.E").WithLocation(24, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "C.Bar()").WithLocation(25, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.E += () => { }").WithLocation(27, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.Field").WithLocation(28, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.Property").WithLocation(29, 17),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.Method()").WithLocation(30, 9)
);
}
} }
} }
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
...@@ -1219,4 +1220,87 @@ public sealed override void Initialize(AnalysisContext context) ...@@ -1219,4 +1220,87 @@ public sealed override void Initialize(AnalysisContext context)
OperationKind.LambdaExpression); OperationKind.LambdaExpression);
} }
} }
public class StaticMemberTestAnalyzer : DiagnosticAnalyzer
{
private const string ReliabilityCategory = "Reliability";
public static readonly DiagnosticDescriptor StaticMemberDescriptor = new DiagnosticDescriptor(
"StaticMember",
"Static member found",
"A static member reference expression is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
// We should not see this warning triggered by any code
public static readonly DiagnosticDescriptor StaticMemberWithInstanceDescriptor = new DiagnosticDescriptor(
"StaticMemberWithInstance",
"Static member with non null Instance found",
"A static member reference with non null Instance is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(StaticMemberDescriptor,
StaticMemberWithInstanceDescriptor); }
}
public sealed override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction(
(operationContext) =>
{
var operation = operationContext.Operation;
ISymbol memberSymbol;
IExpression receiver;
switch (operation.Kind)
{
case OperationKind.FieldReferenceExpression:
memberSymbol = ((IFieldReferenceExpression)operation).Field;
receiver = ((IFieldReferenceExpression)operation).Instance;
break;
case OperationKind.PropertyReferenceExpression:
memberSymbol = ((IPropertyReferenceExpression)operation).Property;
receiver = ((IPropertyReferenceExpression)operation).Instance;
break;
case OperationKind.EventReferenceExpression:
memberSymbol = ((IEventReferenceExpression)operation).Event;
receiver = ((IEventReferenceExpression)operation).Instance;
break;
case OperationKind.MethodBindingExpression:
memberSymbol = ((IMethodBindingExpression)operation).Method;
receiver = ((IMethodBindingExpression)operation).Instance;
break;
case OperationKind.InvocationExpression:
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();
}
if (memberSymbol.IsStatic)
{
operationContext.ReportDiagnostic(Diagnostic.Create(StaticMemberDescriptor, operation.Syntax.GetLocation()));
if (receiver != null)
{
operationContext.ReportDiagnostic(Diagnostic.Create(StaticMemberWithInstanceDescriptor, operation.Syntax.GetLocation()));
}
}
},
OperationKind.FieldReferenceExpression,
OperationKind.PropertyReferenceExpression,
OperationKind.EventReferenceExpression,
OperationKind.MethodBindingExpression,
OperationKind.InvocationExpression,
OperationKind.EventAssignmentExpression);
}
}
} }
\ No newline at end of file
...@@ -342,7 +342,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -342,7 +342,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IInvocationExpression.Instance Private ReadOnly Property IInstance As IExpression Implements IInvocationExpression.Instance
Get Get
Return Me.ReceiverOpt If Me.Method.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get End Get
End Property End Property
...@@ -1385,7 +1389,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1385,7 +1389,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get Get
Return Me.ReceiverOpt If Me.PropertySymbol.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get End Get
End Property End Property
...@@ -1419,7 +1427,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1419,7 +1427,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get Get
Return Me.ReceiverOpt If Me.EventSymbol.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get End Get
End Property End Property
...@@ -1453,7 +1465,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1453,7 +1465,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get Get
Return Me.ReceiverOpt If Me.Method.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get End Get
End Property End Property
...@@ -1499,7 +1515,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1499,7 +1515,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get Get
Return Me.ReceiverOpt If Me.FieldSymbol.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get End Get
End Property End Property
......
...@@ -1442,6 +1442,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1442,6 +1442,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public ReadOnly Property EventInstance As IExpression Implements IEventAssignmentExpression.EventInstance Public ReadOnly Property EventInstance As IExpression Implements IEventAssignmentExpression.EventInstance
Get Get
If [Event].IsStatic Then
Return Nothing
End If
Dim eventAccess As BoundEventAccess = TryCast(_statement.EventAccess, BoundEventAccess) Dim eventAccess As BoundEventAccess = TryCast(_statement.EventAccess, BoundEventAccess)
If eventAccess IsNot Nothing Then If eventAccess IsNot Nothing Then
Return eventAccess.ReceiverOpt Return eventAccess.ReceiverOpt
......
...@@ -4,6 +4,7 @@ Imports System.Collections.Immutable ...@@ -4,6 +4,7 @@ Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics
Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage
Imports Roslyn.Test.Utilities
Imports Xunit Imports Xunit
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
...@@ -1377,5 +1378,57 @@ End Class ...@@ -1377,5 +1378,57 @@ End Class
Return value + 1 Return value + 1
End Function").WithLocation(10, 50)) End Function").WithLocation(10, 50))
End Sub End Sub
<WorkItem(8385, "https://github.com/dotnet/roslyn/issues/8385")>
<Fact>
Public Sub StaticMemberReferenceVisualBasic()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class D
Public Shared Event E()
Public Shared Field As Integer
Public Shared Property P As Integer
Public Shared Sub Method()
End Sub
End Class
Class C
Public Shared Event E()
Public Shared Sub Bar()
End Sub
Public Sub Foo()
AddHandler C.E, AddressOf D.Method
RaiseEvent E() ' Can't raise static event with type in VB
C.Bar()
AddHandler D.E, Sub()
End Sub
D.Field = 1
Dim x = D.P
D.Method()
End Sub
End Class
]]>
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New StaticMemberTestAnalyzer}, Nothing, Nothing, False,
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "AddHandler C.E, AddressOf D.Method").WithLocation(19, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "AddressOf D.Method").WithLocation(19, 25),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "E").WithLocation(20, 20),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "C.Bar()").WithLocation(21, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "AddHandler D.E, Sub()
End Sub").WithLocation(23, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.Field").WithLocation(25, 9),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.P").WithLocation(26, 17),
Diagnostic(StaticMemberTestAnalyzer.StaticMemberDescriptor.Id, "D.Method()").WithLocation(27, 9))
End Sub
End Class End Class
End Namespace End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册