提交 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
{
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;
......@@ -299,7 +299,7 @@ public override void Accept(OperationVisitor visitor)
partial class BoundFieldAccess : IFieldReferenceExpression
{
IExpression IMemberReferenceExpression.Instance => this.ReceiverOpt;
IExpression IMemberReferenceExpression.Instance => this.FieldSymbol.IsStatic? null : this.ReceiverOpt;
ISymbol IMemberReferenceExpression.Member => this.FieldSymbol;
......@@ -322,7 +322,7 @@ partial class BoundPropertyAccess : IPropertyReferenceExpression
{
IPropertySymbol IPropertyReferenceExpression.Property => this.PropertySymbol;
IExpression IMemberReferenceExpression.Instance => this.ReceiverOpt;
IExpression IMemberReferenceExpression.Instance => this.PropertySymbol.IsStatic ? null : this.ReceiverOpt;
ISymbol IMemberReferenceExpression.Member => this.PropertySymbol;
......@@ -343,7 +343,7 @@ partial class BoundEventAccess : IEventReferenceExpression
{
IEventSymbol IEventReferenceExpression.Event => this.EventSymbol;
IExpression IMemberReferenceExpression.Instance => this.ReceiverOpt;
IExpression IMemberReferenceExpression.Instance => this.EventSymbol.IsStatic ? null : this.ReceiverOpt;
ISymbol IMemberReferenceExpression.Member => this.EventSymbol;
......@@ -364,7 +364,7 @@ partial class BoundEventAssignmentOperator : IEventAssignmentExpression
{
IEventSymbol IEventAssignmentExpression.Event => this.Event;
IExpression IEventAssignmentExpression.EventInstance => this.ReceiverOpt;
IExpression IEventAssignmentExpression.EventInstance => this.Event.IsStatic ? null : this.ReceiverOpt;
IExpression IEventAssignmentExpression.HandlerValue => this.Argument;
......
......@@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
......@@ -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.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.
using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -1219,4 +1220,87 @@ public sealed override void Initialize(AnalysisContext context)
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
Private ReadOnly Property IInstance As IExpression Implements IInvocationExpression.Instance
Get
Return Me.ReceiverOpt
If Me.Method.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get
End Property
......@@ -1385,7 +1389,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get
Return Me.ReceiverOpt
If Me.PropertySymbol.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get
End Property
......@@ -1419,7 +1427,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get
Return Me.ReceiverOpt
If Me.EventSymbol.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get
End Property
......@@ -1453,7 +1465,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get
Return Me.ReceiverOpt
If Me.Method.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get
End Property
......@@ -1499,7 +1515,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly Property IInstance As IExpression Implements IMemberReferenceExpression.Instance
Get
Return Me.ReceiverOpt
If Me.FieldSymbol.IsShared Then
Return Nothing
Else
Return Me.ReceiverOpt
End If
End Get
End Property
......
......@@ -1442,6 +1442,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public ReadOnly Property EventInstance As IExpression Implements IEventAssignmentExpression.EventInstance
Get
If [Event].IsStatic Then
Return Nothing
End If
Dim eventAccess As BoundEventAccess = TryCast(_statement.EventAccess, BoundEventAccess)
If eventAccess IsNot Nothing Then
Return eventAccess.ReceiverOpt
......
......@@ -4,6 +4,7 @@ Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics
Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage
Imports Roslyn.Test.Utilities
Imports Xunit
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
......@@ -1377,5 +1378,57 @@ End Class
Return value + 1
End Function").WithLocation(10, 50))
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 Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册