提交 c79061bc 编写于 作者: M Manish Vasani

Return attribute operations as operation blocks for operation block analyzers

Fixes #23309
上级 aeb5360b
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
VisualStudioVersion = 15.0.27102.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeAnalysisTest", "src\Compilers\Core\CodeAnalysisTest\CodeAnalysisTest.csproj", "{A4C99B85-765C-4C65-9C2A-BB609AAB09E6}"
EndProject
......@@ -146,6 +146,10 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "BasicCodeStyleFixes", "src\
EndProject
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "BasicCodeStyleTests", "src\CodeStyle\VisualBasic\Tests\BasicCodeStyleTests.vbproj", "{E512C6C1-F085-4AD7-B0D9-E8F1A0A2A510}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CSharpAnalyzerDriver", "src\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.shproj", "{54E08BF5-F819-404F-A18D-0AB9EA81EA04}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "BasicAnalyzerDriver", "src\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.shproj", "{E8F0BAA5-7327-43D1-9A51-644E81AE55F1}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Compilers\Core\CommandLine\CommandLine.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
......@@ -156,6 +160,7 @@ Global
src\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.projitems*{2523d0e6-df32-4a3e-8ae0-a19bffae2ef6}*SharedItemsImports = 4
src\Compilers\Server\ServerShared\ServerShared.projitems*{32691768-af9c-4cae-9d0f-10721091b9aa}*SharedItemsImports = 13
src\Compilers\Core\CommandLine\CommandLine.projitems*{4b45ca0c-03a0-400f-b454-3d4bcb16af38}*SharedItemsImports = 4
src\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems*{54e08bf5-f819-404f-a18d-0ab9ea81ea04}*SharedItemsImports = 13
src\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{7ad4fe65-9a30-41a6-8004-aa8f89bcb7f3}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{9508f118-f62e-4c16-a6f4-7c3b56e166ad}*SharedItemsImports = 4
......@@ -168,6 +173,7 @@ Global
src\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{d0bc9be7-24f6-40ca-8dc6-fcb93bd44b34}*SharedItemsImports = 13
src\Dependencies\CodeAnalysis.Debugging\Microsoft.CodeAnalysis.Debugging.projitems*{d73adf7d-2c1c-42ae-b2ab-edc9497e4b71}*SharedItemsImports = 13
src\Compilers\Core\CommandLine\CommandLine.projitems*{e58ee9d7-1239-4961-a0c1-f9ec3952c4c1}*SharedItemsImports = 4
src\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.projitems*{e8f0baa5-7327-43d1-9a51-644e81ae55f1}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -469,6 +475,8 @@ Global
{2531A8C4-97DD-47BC-A79C-B7846051E137} = {B20208C3-D3A6-4020-A274-6BE3786D29FB}
{0141285D-8F6C-42C7-BAF3-3C0CCD61C716} = {B20208C3-D3A6-4020-A274-6BE3786D29FB}
{E512C6C1-F085-4AD7-B0D9-E8F1A0A2A510} = {B20208C3-D3A6-4020-A274-6BE3786D29FB}
{54E08BF5-F819-404F-A18D-0AB9EA81EA04} = {32A48625-F0AD-419D-828B-A50BDABA38EA}
{E8F0BAA5-7327-43D1-9A51-644E81AE55F1} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6F599E08-A9EA-4FAA-897F-5D824B0210E6}
......
......@@ -82,7 +82,8 @@ private static bool InvalidLevel(int? level)
{
var t = (TypeDeclarationSyntax)node;
foreach (var decl in t.Members) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken);
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken));
var attributes = GetAttributes(t);
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken));
return;
}
......@@ -90,20 +91,24 @@ private static bool InvalidLevel(int? level)
{
var t = (EnumDeclarationSyntax)node;
foreach (var decl in t.Members) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken);
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken));
var attributes = GetAttributes(t.AttributeLists);
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken));
return;
}
case SyntaxKind.EnumMemberDeclaration:
{
var t = (EnumMemberDeclarationSyntax)node;
builder.Add(GetDeclarationInfo(model, node, getSymbol, t.EqualsValue, cancellationToken));
var attributes = GetAttributes(t.AttributeLists);
var codeBlocks = SpecializedCollections.SingletonEnumerable(t.EqualsValue).Concat(attributes);
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken));
return;
}
case SyntaxKind.DelegateDeclaration:
{
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken));
var attributes = GetAttributes(((DelegateDeclarationSyntax)node).AttributeLists);
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken));
return;
}
......@@ -111,7 +116,8 @@ private static bool InvalidLevel(int? level)
{
var t = (EventDeclarationSyntax)node;
foreach (var decl in t.AccessorList.Accessors) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken);
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken));
var attributes = GetAttributes(t.AttributeLists);
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken));
return;
}
......@@ -119,9 +125,11 @@ private static bool InvalidLevel(int? level)
case SyntaxKind.FieldDeclaration:
{
var t = (BaseFieldDeclarationSyntax)node;
var attributes = GetAttributes(t.AttributeLists);
foreach (var decl in t.Declaration.Variables)
{
builder.Add(GetDeclarationInfo(model, decl, getSymbol, decl.Initializer, cancellationToken));
var codeBlocks = SpecializedCollections.SingletonEnumerable(decl.Initializer).Concat(attributes);
builder.Add(GetDeclarationInfo(model, decl, getSymbol, codeBlocks, cancellationToken));
}
return;
......@@ -152,7 +160,9 @@ private static bool InvalidLevel(int? level)
ComputeDeclarations(model, t.ExpressionBody, shouldSkip, getSymbol, builder, levelsToCompute, cancellationToken);
}
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken, t.Initializer));
var attributes = GetAttributes(t.AttributeLists);
var codeBlocks = SpecializedCollections.SingletonEnumerable(t.Initializer).Concat(attributes);
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken));
return;
}
......@@ -173,6 +183,8 @@ private static bool InvalidLevel(int? level)
}
var codeBlocks = t.ParameterList != null ? t.ParameterList.Parameters.Select(p => p.Default) : SpecializedCollections.EmptyEnumerable<SyntaxNode>();
var attributes = GetAttributes(t.AttributeLists);
codeBlocks = codeBlocks.Concat(attributes);
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken));
return;
......@@ -187,6 +199,7 @@ private static bool InvalidLevel(int? level)
var blocks = ArrayBuilder<SyntaxNode>.GetInstance();
blocks.AddIfNotNull(t.Body);
blocks.AddIfNotNull(t.ExpressionBody);
blocks.AddRange(GetAttributes(t.AttributeLists));
builder.Add(GetDeclarationInfo(model, node, getSymbol, blocks, cancellationToken));
blocks.Free();
......@@ -215,6 +228,8 @@ private static bool InvalidLevel(int? level)
codeBlocks = codeBlocks.Concat(expressionBody);
}
codeBlocks = codeBlocks.Concat(GetAttributes(t.AttributeLists));
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken));
return;
}
......@@ -231,6 +246,35 @@ private static bool InvalidLevel(int? level)
}
}
private static IEnumerable<SyntaxNode> GetAttributes(TypeDeclarationSyntax typeDeclaration)
{
switch (typeDeclaration.Kind())
{
case SyntaxKind.ClassDeclaration:
return GetAttributes(((ClassDeclarationSyntax)typeDeclaration).AttributeLists);
case SyntaxKind.StructDeclaration:
return GetAttributes(((StructDeclarationSyntax)typeDeclaration).AttributeLists);
case SyntaxKind.InterfaceDeclaration:
return GetAttributes(((InterfaceDeclarationSyntax)typeDeclaration).AttributeLists);
default:
return SpecializedCollections.EmptyEnumerable<SyntaxNode>();
}
}
private static IEnumerable<SyntaxNode> GetAttributes(SyntaxList<AttributeListSyntax> attributeLists)
{
foreach (var attributeList in attributeLists)
{
foreach (var attribute in attributeList.Attributes)
{
yield return attribute;
}
}
}
private static DeclarationInfo GetExpressionBodyDeclarationInfo(
BasePropertyDeclarationSyntax declarationWithExpressionBody,
ArrowExpressionClauseSyntax expressionBody,
......
......@@ -2108,5 +2108,175 @@ private void ReportDiagnosticsCore(Action<Diagnostic> addDiagnostic, Location lo
addDiagnostic(diagnostic);
}
}
[Fact, WorkItem(23309, "https://github.com/dotnet/roslyn/issues/23309")]
public void TestFieldReferenceAnalyzer_InAttributes()
{
string source = @"
using System;
internal class MyAttribute : Attribute
{
public MyAttribute(int f) { }
}
internal interface MyInterface
{
event EventHandler MyEvent;
}
[MyAttribute(FieldForClass)]
internal class C : MyInterface
{
private const int FieldForClass = 1, FieldForStruct = 2, FieldForInterface = 3, FieldForField = 4, FieldForMethod = 5,
FieldForEnum = 6, FieldForEnumMember = 7, FieldForDelegate = 8, FieldForEventField = 9, FieldForEvent = 10,
FieldForAddHandler = 11, FieldForRemoveHandler = 12, FieldForProperty = 13, FieldForPropertyGetter = 14, FieldForPropertySetter = 15,
FieldForIndexer = 16, FieldForIndexerGetter = 17, FieldForIndexerSetter = 18, FieldForExpressionBodiedMethod = 19, FieldForExpressionBodiedProperty = 20;
[MyAttribute(FieldForStruct)]
private struct S { }
[MyAttribute(FieldForInterface)]
private interface I { }
[MyAttribute(FieldForField)]
private int field2 = 0, field3 = 0;
[MyAttribute(FieldForMethod)]
private void M1() { }
[MyAttribute(FieldForEnum)]
private enum E
{
[MyAttribute(FieldForEnumMember)]
F = 0
}
[MyAttribute(FieldForDelegate)]
public delegate void Delegate();
[MyAttribute(FieldForEventField)]
public event Delegate MyEvent;
[MyAttribute(FieldForEvent)]
event EventHandler MyInterface.MyEvent
{
[MyAttribute(FieldForAddHandler)]
add
{
}
[MyAttribute(FieldForRemoveHandler)]
remove
{
}
}
[MyAttribute(FieldForProperty)]
private int P1
{
[MyAttribute(FieldForPropertyGetter)]
get;
[MyAttribute(FieldForPropertySetter)]
set;
}
[MyAttribute(FieldForIndexer)]
private int this[int index]
{
[MyAttribute(FieldForIndexerGetter)]
get { return 0; }
[MyAttribute(FieldForIndexerSetter)]
set { }
}
[MyAttribute(FieldForExpressionBodiedMethod)]
private int M2 => 0;
[MyAttribute(FieldForExpressionBodiedProperty)]
private int P2 => 0;
}
";
var tree = CSharpSyntaxTree.ParseText(source);
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics(
// (45,27): warning CS0067: The event 'C.MyEvent' is never used
// public event Delegate MyEvent;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "MyEvent").WithArguments("C.MyEvent").WithLocation(45, 27),
// (29,17): warning CS0414: The field 'C.field2' is assigned but its value is never used
// private int field2 = 0, field3 = 0;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "field2").WithArguments("C.field2").WithLocation(29, 17),
// (29,29): warning CS0414: The field 'C.field3' is assigned but its value is never used
// private int field2 = 0, field3 = 0;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "field3").WithArguments("C.field3").WithLocation(29, 29));
// Test RegisterOperationBlockAction
TestFieldReferenceAnalyzer_InAttributes_Core(compilation, doOperationBlockAnalysis: true);
// Test RegisterOperationAction
TestFieldReferenceAnalyzer_InAttributes_Core(compilation, doOperationBlockAnalysis: false);
}
private static void TestFieldReferenceAnalyzer_InAttributes_Core(Compilation compilation, bool doOperationBlockAnalysis)
{
var analyzers = new DiagnosticAnalyzer[] { new FieldReferenceOperationAnalyzer(doOperationBlockAnalysis) };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("ID", "FieldForClass").WithArguments("FieldForClass", "1").WithLocation(14, 14),
Diagnostic("ID", "FieldForStruct").WithArguments("FieldForStruct", "2").WithLocation(22, 18),
Diagnostic("ID", "FieldForInterface").WithArguments("FieldForInterface", "3").WithLocation(25, 18),
Diagnostic("ID", "FieldForField").WithArguments("FieldForField", "4").WithLocation(28, 18),
Diagnostic("ID", "FieldForField").WithArguments("FieldForField", "4").WithLocation(28, 18),
Diagnostic("ID", "FieldForMethod").WithArguments("FieldForMethod", "5").WithLocation(31, 18),
Diagnostic("ID", "FieldForEnum").WithArguments("FieldForEnum", "6").WithLocation(34, 18),
Diagnostic("ID", "FieldForEnumMember").WithArguments("FieldForEnumMember", "7").WithLocation(37, 22),
Diagnostic("ID", "FieldForDelegate").WithArguments("FieldForDelegate", "8").WithLocation(41, 18),
Diagnostic("ID", "FieldForEventField").WithArguments("FieldForEventField", "9").WithLocation(44, 18),
Diagnostic("ID", "FieldForEvent").WithArguments("FieldForEvent", "10").WithLocation(47, 18),
Diagnostic("ID", "FieldForAddHandler").WithArguments("FieldForAddHandler", "11").WithLocation(50, 22),
Diagnostic("ID", "FieldForRemoveHandler").WithArguments("FieldForRemoveHandler", "12").WithLocation(54, 22),
Diagnostic("ID", "FieldForProperty").WithArguments("FieldForProperty", "13").WithLocation(60, 18),
Diagnostic("ID", "FieldForPropertyGetter").WithArguments("FieldForPropertyGetter", "14").WithLocation(63, 22),
Diagnostic("ID", "FieldForPropertySetter").WithArguments("FieldForPropertySetter", "15").WithLocation(65, 22),
Diagnostic("ID", "FieldForIndexer").WithArguments("FieldForIndexer", "16").WithLocation(69, 18),
Diagnostic("ID", "FieldForIndexerGetter").WithArguments("FieldForIndexerGetter", "17").WithLocation(72, 22),
Diagnostic("ID", "FieldForIndexerSetter").WithArguments("FieldForIndexerSetter", "18").WithLocation(74, 22),
Diagnostic("ID", "FieldForExpressionBodiedMethod").WithArguments("FieldForExpressionBodiedMethod", "19").WithLocation(78, 18),
Diagnostic("ID", "FieldForExpressionBodiedProperty").WithArguments("FieldForExpressionBodiedProperty", "20").WithLocation(81, 18));
}
[Fact, WorkItem(23309, "https://github.com/dotnet/roslyn/issues/23309")]
public void TestFieldReferenceAnalyzer_InConstructorInitializer()
{
string source = @"
internal class Base
{
protected Base(int i) { }
}
internal class Derived : Base
{
private const int Field = 0;
public Derived() : base(Field)
{
}
}";
var tree = CSharpSyntaxTree.ParseText(source);
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
// Test RegisterOperationBlockAction
TestFieldReferenceAnalyzer_InConstructorInitializer_Core(compilation, doOperationBlockAnalysis: true);
// Test RegisterOperationAction
TestFieldReferenceAnalyzer_InConstructorInitializer_Core(compilation, doOperationBlockAnalysis: false);
}
private static void TestFieldReferenceAnalyzer_InConstructorInitializer_Core(Compilation compilation, bool doOperationBlockAnalysis)
{
var analyzers = new DiagnosticAnalyzer[] { new FieldReferenceOperationAnalyzer(doOperationBlockAnalysis) };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("ID", "Field").WithArguments("Field", "0").WithLocation(11, 29));
}
}
}
......@@ -61,16 +61,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
For Each decl In t.Members
ComputeDeclarationsCore(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken)
Next
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken))
Dim attributes = GetAttributes(t.EnumStatement.AttributeLists)
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken))
Return
Case SyntaxKind.EnumStatement
Dim t = CType(node, EnumStatementSyntax)
Dim attributes = GetAttributes(t.AttributeLists)
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken))
Return
Case SyntaxKind.EnumMemberDeclaration
Dim t = CType(node, EnumMemberDeclarationSyntax)
builder.Add(GetDeclarationInfo(model, node, getSymbol, t.Initializer, cancellationToken))
Dim attributes = GetAttributes(t.AttributeLists)
Dim codeBlocks = SpecializedCollections.SingletonEnumerable(Of SyntaxNode)(t.Initializer).Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
Case SyntaxKind.DelegateSubStatement, SyntaxKind.DelegateFunctionStatement
Dim t = CType(node, DelegateStatementSyntax)
Dim paramInitializers As IEnumerable(Of SyntaxNode) = GetParameterInitializers(t.ParameterList)
builder.Add(GetDeclarationInfo(model, node, getSymbol, paramInitializers, cancellationToken))
Dim attributes = GetAttributes(t.AttributeLists)
Dim codeBlocks = paramInitializers.Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
Case SyntaxKind.EventBlock
Dim t = CType(node, EventBlockSyntax)
......@@ -78,19 +88,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
ComputeDeclarationsCore(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken)
Next
Dim eventInitializers = GetParameterInitializers(t.EventStatement.ParameterList)
builder.Add(GetDeclarationInfo(model, node, getSymbol, eventInitializers, cancellationToken))
Dim attributes = GetAttributes(t.EventStatement.AttributeLists)
Dim codeBlocks = eventInitializers.Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
Case SyntaxKind.EventStatement
Dim t = CType(node, EventStatementSyntax)
Dim paramInitializers = GetParameterInitializers(t.ParameterList)
builder.Add(GetDeclarationInfo(model, node, getSymbol, paramInitializers, cancellationToken))
Dim attributes = GetAttributes(t.AttributeLists)
Dim codeBlocks = paramInitializers.Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
Case SyntaxKind.FieldDeclaration
Dim t = CType(node, FieldDeclarationSyntax)
Dim attributes = GetAttributes(t.AttributeLists)
For Each decl In t.Declarators
Dim initializer = GetInitializerNode(decl)
Dim codeBlocks = SpecializedCollections.SingletonEnumerable(initializer).Concat(attributes)
For Each identifier In decl.Names
builder.Add(GetDeclarationInfo(model, identifier, getSymbol, initializer, cancellationToken))
builder.Add(GetDeclarationInfo(model, identifier, getSymbol, codeBlocks, cancellationToken))
Next
Next
Return
......@@ -100,12 +116,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
ComputeDeclarationsCore(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken)
Next
Dim propertyInitializers = GetInitializerNodes(t.PropertyStatement)
builder.Add(GetDeclarationInfo(model, node, getSymbol, propertyInitializers, cancellationToken))
Dim attributes = GetAttributes(t.PropertyStatement.AttributeLists)
Dim codeBlocks = propertyInitializers.Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
Case SyntaxKind.PropertyStatement
Dim t = CType(node, PropertyStatementSyntax)
Dim propertyInitializers = GetInitializerNodes(t)
builder.Add(GetDeclarationInfo(model, node, getSymbol, propertyInitializers, cancellationToken))
Dim attributes = GetAttributes(t.AttributeLists)
Dim codeBlocks = propertyInitializers.Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
Case SyntaxKind.CompilationUnit
Dim t = CType(node, CompilationUnitSyntax)
......@@ -119,20 +139,23 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
For Each decl In typeBlock.Members
ComputeDeclarationsCore(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken)
Next
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken))
Dim attributes = GetAttributes(typeBlock.BlockStatement.AttributeLists)
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken))
Return
End If
Dim typeStatement = TryCast(node, TypeStatementSyntax)
If typeStatement IsNot Nothing Then
builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken))
Dim attributes = GetAttributes(typeStatement.AttributeLists)
builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken))
Return
End If
Dim methodBlock = TryCast(node, MethodBlockBaseSyntax)
If methodBlock IsNot Nothing Then
Dim paramInitializers = GetParameterInitializers(methodBlock.BlockStatement.ParameterList)
Dim codeBlocks = paramInitializers.Concat(methodBlock)
Dim attributes = GetAttributes(methodBlock.BlockStatement.AttributeLists)
Dim codeBlocks = paramInitializers.Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
End If
......@@ -140,7 +163,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim methodStatement = TryCast(node, MethodBaseSyntax)
If methodStatement IsNot Nothing Then
Dim paramInitializers = GetParameterInitializers(methodStatement.ParameterList)
builder.Add(GetDeclarationInfo(model, node, getSymbol, paramInitializers, cancellationToken))
Dim attributes = GetAttributes(methodStatement.AttributeLists)
Dim codeBlocks = paramInitializers.Concat(attributes)
builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken))
Return
End If
......@@ -148,6 +173,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Select
End Sub
Private Shared Iterator Function GetAttributes(attributeLists As SyntaxList(Of AttributeListSyntax)) As IEnumerable(Of SyntaxNode)
For Each attributeList In attributeLists
For Each attribute In attributeList.Attributes
Yield attribute
Next
Next
End Function
Private Shared Function GetParameterInitializers(parameterList As ParameterListSyntax) As IEnumerable(Of SyntaxNode)
Return If(parameterList IsNot Nothing,
parameterList.Parameters.Select(Function(p) p.Default),
......
......@@ -1261,5 +1261,134 @@ End Class
Dim diag = Diagnostic(diagnosticId, squiggledText).WithArguments(arguments).WithLocation(line, column)
builder.Add(diag)
End Sub
<Fact, WorkItem(23309, "https://github.com/dotnet/roslyn/issues/23309")>
Public Sub TestFieldReferenceAnalyzer_InAttributes()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Imports System
Friend Class MyAttribute
Inherits Attribute
Public Sub New(f As Integer)
End Sub
End Class
Friend Interface MyInterface
Event MyEvent As EventHandler
End Interface
<MyAttribute(C.FieldForClass)>
Friend Class C
Implements MyInterface
Friend Const FieldForClass As Integer = 1, FieldForStruct As Integer = 2, FieldForInterface As Integer = 3, FieldForField As Integer = 4, FieldForMethod As Integer = 5,
FieldForEnum As Integer = 6, FieldForEnumMember As Integer = 7, FieldForDelegateSub As Integer = 8, FieldForDelegateFunction As Integer = 9, FieldForEventField As Integer = 10,
FieldForEvent As Integer = 11, FieldForAddHandler As Integer = 12, FieldForRemoveHandler As Integer = 13, FieldForRaiseHandler As Integer = 14, FieldForProperty As Integer = 15,
FieldForPropertyGetter As Integer = 16, FieldForPropertySetter As Integer = 17, FieldForIndexer As Integer = 18, FieldForIndexerGetter As Integer = 19, FieldForIndexerSetter As Integer = 20
<MyAttribute(FieldForStruct)>
Private Structure S
End Structure
<MyAttribute(FieldForInterface)>
Private Interface I
End Interface
<MyAttribute(FieldForField)>
Private field2 As Integer = 0, field3 As Integer = 0
<MyAttribute(FieldForMethod)>
Private Sub M1()
End Sub
<MyAttribute(FieldForEnum)>
Private Enum E
<MyAttribute(FieldForEnumMember)>
F = 0
End Enum
<MyAttribute(FieldForDelegateSub)>
Public Delegate Sub [Delegate]()
<MyAttribute(FieldForDelegateFunction)>
Public Delegate Function Delegate2()
<MyAttribute(FieldForEventField)>
Public Event MyEvent As [Delegate]
<MyAttribute(FieldForEvent)>
Private Custom Event MyEvent2 As EventHandler Implements MyInterface.MyEvent
<MyAttribute(FieldForAddHandler)>
AddHandler(ByVal value As EventHandler)
End AddHandler
<MyAttribute(FieldForRemoveHandler)>
RemoveHandler(ByVal value As EventHandler)
End RemoveHandler
<MyAttribute(FieldForRaiseHandler)>
RaiseEvent()
End RaiseEvent
End Event
<MyAttribute(FieldForProperty)>
Private Property P1() As Integer
<MyAttribute(FieldForPropertyGetter)>
Get
Return 0
End Get
<MyAttribute(FieldForPropertySetter)>
Set
End Set
End Property
<MyAttribute(FieldForIndexer)>
Default Property Item(index As Integer) As Integer
<MyAttribute(FieldForIndexerGetter)>
Get
Return 0
End Get
<MyAttribute(FieldForIndexerSetter)>
Set
End Set
End Property
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
' Test RegisterOperationBlockAction
TestFieldReferenceAnalyzer_InAttributes_Core(comp, doOperationBlockAnalysis:=True)
' Test RegisterOperationAction
TestFieldReferenceAnalyzer_InAttributes_Core(comp, doOperationBlockAnalysis:=False)
End Sub
Private Shared Sub TestFieldReferenceAnalyzer_InAttributes_Core(comp As Compilation, doOperationBlockAnalysis As Boolean)
comp.VerifyAnalyzerDiagnostics({New FieldReferenceOperationAnalyzer(doOperationBlockAnalysis)}, Nothing, Nothing, False,
Diagnostic("ID", "C.FieldForClass").WithArguments("FieldForClass", "1").WithLocation(13, 14),
Diagnostic("ID", "FieldForStruct").WithArguments("FieldForStruct", "2").WithLocation(21, 18),
Diagnostic("ID", "FieldForInterface").WithArguments("FieldForInterface", "3").WithLocation(25, 18),
Diagnostic("ID", "FieldForField").WithArguments("FieldForField", "4").WithLocation(29, 18),
Diagnostic("ID", "FieldForField").WithArguments("FieldForField", "4").WithLocation(29, 18),
Diagnostic("ID", "FieldForMethod").WithArguments("FieldForMethod", "5").WithLocation(32, 18),
Diagnostic("ID", "FieldForEnum").WithArguments("FieldForEnum", "6").WithLocation(36, 18),
Diagnostic("ID", "FieldForEnumMember").WithArguments("FieldForEnumMember", "7").WithLocation(38, 22),
Diagnostic("ID", "FieldForDelegateSub").WithArguments("FieldForDelegateSub", "8").WithLocation(42, 18),
Diagnostic("ID", "FieldForDelegateFunction").WithArguments("FieldForDelegateFunction", "9").WithLocation(45, 18),
Diagnostic("ID", "FieldForEventField").WithArguments("FieldForEventField", "10").WithLocation(48, 18),
Diagnostic("ID", "FieldForEvent").WithArguments("FieldForEvent", "11").WithLocation(51, 18),
Diagnostic("ID", "FieldForAddHandler").WithArguments("FieldForAddHandler", "12").WithLocation(53, 22),
Diagnostic("ID", "FieldForRemoveHandler").WithArguments("FieldForRemoveHandler", "13").WithLocation(56, 22),
Diagnostic("ID", "FieldForRaiseHandler").WithArguments("FieldForRaiseHandler", "14").WithLocation(59, 22),
Diagnostic("ID", "FieldForProperty").WithArguments("FieldForProperty", "15").WithLocation(64, 18),
Diagnostic("ID", "FieldForPropertyGetter").WithArguments("FieldForPropertyGetter", "16").WithLocation(66, 22),
Diagnostic("ID", "FieldForPropertySetter").WithArguments("FieldForPropertySetter", "17").WithLocation(70, 22),
Diagnostic("ID", "FieldForIndexer").WithArguments("FieldForIndexer", "18").WithLocation(75, 18),
Diagnostic("ID", "FieldForIndexerGetter").WithArguments("FieldForIndexerGetter", "19").WithLocation(77, 22),
Diagnostic("ID", "FieldForIndexerSetter").WithArguments("FieldForIndexerSetter", "20").WithLocation(81, 22))
End Sub
End Class
End Namespace
......@@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using Xunit;
......@@ -868,6 +869,57 @@ public override void Initialize(AnalysisContext context)
}
}
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class FieldReferenceOperationAnalyzer : DiagnosticAnalyzer
{
private readonly bool _doOperationBlockAnalysis;
public static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor(
"ID",
"Title",
"Field {0} = {1}",
"Category",
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public FieldReferenceOperationAnalyzer(bool doOperationBlockAnalysis)
{
_doOperationBlockAnalysis = doOperationBlockAnalysis;
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Descriptor);
public override void Initialize(AnalysisContext context)
{
if (_doOperationBlockAnalysis)
{
context.RegisterOperationBlockAction(operationBlockAnalysisContext =>
{
foreach (var operationBlock in operationBlockAnalysisContext.OperationBlocks)
{
foreach (var operation in operationBlock.DescendantsAndSelf().OfType<IFieldReferenceOperation>())
{
AnalyzerFieldReferenceOperation(operation, operationBlockAnalysisContext.ReportDiagnostic);
}
}
});
}
else
{
context.RegisterOperationAction(AnalyzerOperation, OperationKind.FieldReference);
}
}
private static void AnalyzerOperation(OperationAnalysisContext operationAnalysisContext)
{
AnalyzerFieldReferenceOperation((IFieldReferenceOperation)operationAnalysisContext.Operation, operationAnalysisContext.ReportDiagnostic);
}
private static void AnalyzerFieldReferenceOperation(IFieldReferenceOperation operation, Action<Diagnostic> reportDiagnostic)
{
var diagnostic = Diagnostic.Create(Descriptor, operation.Syntax.GetLocation(), operation.Field.Name, operation.Field.ConstantValue);
reportDiagnostic(diagnostic);
}
}
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public class GeneratedCodeAnalyzer : DiagnosticAnalyzer
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册