提交 cf49294c 编写于 作者: D David Poeschl 提交者: GitHub

Merge pull request #13931 from dpoeschl/RegisterSymbolActionForLocals

Make RegisterSymbolAction work on Parameters
......@@ -1655,5 +1655,233 @@ public partial class C33 { }
Diagnostic("UniqueTextFileDiagnostic").WithArguments("Source3_File5.designer.cs").WithLocation(1, 1),
Diagnostic("NumberOfUniqueTextFileDescriptor").WithArguments("3").WithLocation(1, 1));
}
[Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InConstructor()
{
string source = @"
public class C
{
public C(int a, int b)
{
}
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "a").WithLocation(4, 18),
Diagnostic("Parameter_ID", "b").WithLocation(4, 25));
}
[Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InRegularMethod()
{
string source = @"
public class C
{
void M1(string a, string b)
{
}
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "a").WithLocation(4, 20),
Diagnostic("Parameter_ID", "b").WithLocation(4, 30));
}
[Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InIndexers()
{
string source = @"
public class C
{
public int this[int index]
{
get { return 0; }
set { }
}
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "index").WithLocation(4, 25));
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/14061"), WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_Lambdas()
{
string source = @"
public class C
{
void M2()
{
System.Func<int, int, int> x = (int a, int b) => b;
}
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Local_ID", "x").WithLocation(6, 36),
Diagnostic("Parameter_ID", "a").WithLocation(6, 45),
Diagnostic("Parameter_ID", "b").WithLocation(6, 52));
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/14061"), WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InAnonymousMethods()
{
string source = @"
public class C
{
void M3()
{
M4(delegate (int x, int y) { });
}
void M4(System.Action<int, int> a) { }
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "a").WithLocation(9, 37),
Diagnostic("Parameter_ID", "x").WithLocation(6, 26),
Diagnostic("Parameter_ID", "y").WithLocation(6, 33));
}
[Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InDelegateTypes()
{
string source = @"
public class C
{
delegate void D(int x, string y);
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "x").WithLocation(4, 25),
Diagnostic("Parameter_ID", "y").WithLocation(4, 35));
}
[Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InOperators()
{
string source = @"
public class C
{
public static implicit operator int (C c) { return 0; }
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "c").WithLocation(4, 44));
}
[Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InExplicitInterfaceImplementations()
{
string source = @"
interface I
{
void M(int a, int b);
}
public class C : I
{
void I.M(int c, int d) { }
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "c").WithLocation(9, 18),
Diagnostic("Parameter_ID", "d").WithLocation(9, 25),
Diagnostic("Parameter_ID", "a").WithLocation(4, 16),
Diagnostic("Parameter_ID", "b").WithLocation(4, 23));
}
[Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InExtensionMethods()
{
string source = @"
public static class C
{
static void M(this int x, int y) { }
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "x").WithLocation(4, 28),
Diagnostic("Parameter_ID", "y").WithLocation(4, 35));
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/14061"), WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")]
public void TestParametersAnalyzer_InLocalFunctions()
{
string source = @"
public class C
{
void M1()
{
M2(1, 2);
void M2(int a, int b)
{
}
}
}
";
var tree = CSharpSyntaxTree.ParseText(source, path: "Source.cs");
var compilation = CreateCompilationWithMscorlib45(new[] { tree });
compilation.VerifyDiagnostics();
var analyzers = new DiagnosticAnalyzer[] { new AnalyzerForParameters() };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
Diagnostic("Parameter_ID", "a").WithLocation(4, 18), // ctor
Diagnostic("Parameter_ID", "b").WithLocation(4, 25),
Diagnostic("Local_ID", "c").WithLocation(6, 13),
Diagnostic("Local_ID", "d").WithLocation(6, 20),
Diagnostic("Parameter_ID", "a").WithLocation(10, 20), // M1
Diagnostic("Parameter_ID", "b").WithLocation(10, 30),
Diagnostic("Local_ID", "c").WithLocation(12, 11),
Diagnostic("Local_ID", "x").WithLocation(18, 36), // M2
Diagnostic("Parameter_ID", "a").WithLocation(26, 37), // M4
Diagnostic("Parameter_ID", "index").WithLocation(28, 25)); // indexer
}
}
}
......@@ -701,6 +701,8 @@ public struct SymbolAnalysisContext
/// </summary>
public CancellationToken CancellationToken { get { return _cancellationToken; } }
internal Func<Diagnostic, bool> IsSupportedDiagnostic => _isSupportedDiagnostic;
public SymbolAnalysisContext(ISymbol symbol, Compilation compilation, AnalyzerOptions options, Action<Diagnostic> reportDiagnostic, Func<Diagnostic, bool> isSupportedDiagnostic, CancellationToken cancellationToken)
{
_symbol = symbol;
......
......@@ -608,6 +608,53 @@ public void RegisterSymbolAction(DiagnosticAnalyzer analyzer, Action<SymbolAnaly
SymbolAnalyzerAction analyzerAction = new SymbolAnalyzerAction(action, symbolKinds, analyzer);
this.GetOrCreateAnalyzerActions(analyzer).AddSymbolAction(analyzerAction);
_symbolActions = _symbolActions.Add(analyzerAction);
// The SymbolAnalyzerAction does not handle SymbolKind.Parameter because the compiler
// does not make CompilationEvents for them. As a workaround, handle them specially by
// registering further SymbolActions (for Methods) and utilize the results to construct
// the necessary SymbolAnalysisContexts.
if (symbolKinds.Contains(SymbolKind.Parameter))
{
RegisterSymbolAction(
analyzer,
context =>
{
ImmutableArray<IParameterSymbol> parameters;
switch (context.Symbol.Kind)
{
case SymbolKind.Method:
parameters = ((IMethodSymbol)context.Symbol).Parameters;
break;
case SymbolKind.Property:
parameters = ((IPropertySymbol)context.Symbol).Parameters;
break;
case SymbolKind.NamedType:
var namedType = (INamedTypeSymbol)context.Symbol;
var delegateInvokeMethod = namedType.DelegateInvokeMethod;
parameters = delegateInvokeMethod?.Parameters ?? ImmutableArray.Create<IParameterSymbol>();
break;
default:
throw new ArgumentException(nameof(context));
}
foreach (var parameter in parameters)
{
if (!parameter.IsImplicitlyDeclared)
{
action(new SymbolAnalysisContext(
parameter,
context.Compilation,
context.Options,
context.ReportDiagnostic,
context.IsSupportedDiagnostic,
context.CancellationToken));
}
}
},
ImmutableArray.Create(SymbolKind.Method, SymbolKind.Property, SymbolKind.NamedType));
}
}
public void RegisterCodeBlockStartAction<TLanguageKindEnum>(DiagnosticAnalyzer analyzer, Action<CodeBlockStartAnalysisContext<TLanguageKindEnum>> action) where TLanguageKindEnum : struct
......
......@@ -981,6 +981,162 @@ End Class
Diagnostic(OwningSymbolTestAnalyzer.ExpressionDescriptor.Id, "12").WithLocation(12, 36))
End Sub
<Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")>
Public Sub TestParametersAnalyzer_InRegularMethods()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Public Sub M(a As Integer, b As String)
End Sub
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, False,
Diagnostic("Parameter_ID", "a").WithLocation(2, 18),
Diagnostic("Parameter_ID", "b").WithLocation(2, 32))
End Sub
<Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")>
Public Sub TestParametersAnalyzer_InConstructors()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Public Sub New(a As Integer, b As String)
End Sub
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, False,
Diagnostic("Parameter_ID", "a").WithLocation(2, 20),
Diagnostic("Parameter_ID", "b").WithLocation(2, 34))
End Sub
<Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")>
Public Sub TestParametersAnalyzer_InIndexers()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Default Public Property Item(a As Integer, b As Integer) As Integer
Get
Return 0
End Get
Set(ByVal Value As Integer)
End Set
End Property
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, False,
Diagnostic("Parameter_ID", "a").WithLocation(2, 34),
Diagnostic("Parameter_ID", "b").WithLocation(2, 48),
Diagnostic("Parameter_ID", "Value").WithLocation(6, 19))
End Sub
<Fact(Skip:="https://github.com/dotnet/roslyn/issues/14062"), WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")>
Public Sub TestParametersAnalyzer_InDelegateTypes()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Delegate Sub DelegateType(a As Integer, b As String)
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, False,
Diagnostic("Parameter_ID", "a").WithLocation(2, 34),
Diagnostic("Parameter_ID", "b").WithLocation(2, 48))
End Sub
<Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")>
Public Sub TestParametersAnalyzer_InOperators()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Public Shared Operator +(ByVal h1 As C, ByVal h2 As C)
Return New C()
End Operator
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, False,
Diagnostic("Parameter_ID", "h1").WithLocation(2, 36),
Diagnostic("Parameter_ID", "h2").WithLocation(2, 51))
End Sub
<Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")>
Public Sub TestParametersAnalyzer_InInterfaceImplementations()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Interface I
Sub M(a As Integer, b As String)
End Interface
Class C
Implements I
Public Sub M(a As Integer, b As String) Implements I.M
End Sub
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, False,
Diagnostic("Parameter_ID", "a").WithLocation(2, 11),
Diagnostic("Parameter_ID", "b").WithLocation(2, 25),
Diagnostic("Parameter_ID", "a").WithLocation(7, 18),
Diagnostic("Parameter_ID", "b").WithLocation(7, 32))
End Sub
<Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")>
Public Sub TestParametersAnalyzer_InParameterizedProperties()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Public ReadOnly Property Test(a As Integer, b As String) As Integer
Get
Return 1
End Get
End Property
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, False,
Diagnostic("Parameter_ID", "a").WithLocation(2, 35),
Diagnostic("Parameter_ID", "b").WithLocation(2, 49))
End Sub
Private Shared Sub VerifyGeneratedCodeAnalyzerDiagnostics(compilation As Compilation, isGeneratedFileName As Func(Of String, Boolean), generatedCodeAnalysisFlagsOpt As GeneratedCodeAnalysisFlags?)
Dim expected = GetExpectedGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFileName, generatedCodeAnalysisFlagsOpt)
VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, generatedCodeAnalysisFlagsOpt)
......
......@@ -1067,5 +1067,29 @@ private void OnCompilationStart(CompilationStartAnalysisContext context)
});
}
}
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public class AnalyzerForParameters : DiagnosticAnalyzer
{
public static readonly DiagnosticDescriptor ParameterDescriptor = new DiagnosticDescriptor(
"Parameter_ID",
"Parameter_Title",
"Parameter_Message",
"Parameter_Category",
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ParameterDescriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolAction(SymbolAction, SymbolKind.Parameter);
}
private void SymbolAction(SymbolAnalysisContext context)
{
context.ReportDiagnostic(Diagnostic.Create(ParameterDescriptor, context.Symbol.Locations[0]));
}
}
}
}
\ No newline at end of file
......@@ -75,7 +75,11 @@ public void VerifyAllAnalyzerMembersWereCalled()
public void VerifyAnalyzeSymbolCalledForAllSymbolKinds()
{
var expectedSymbolKinds = new[] { SymbolKind.Event, SymbolKind.Field, SymbolKind.Method, SymbolKind.NamedType, SymbolKind.Namespace, SymbolKind.Property };
var expectedSymbolKinds = new[]
{
SymbolKind.Event, SymbolKind.Field, SymbolKind.Method, SymbolKind.NamedType, SymbolKind.Namespace, SymbolKind.Parameter, SymbolKind.Property
};
var actualSymbolKinds = _callLog.Where(a => FilterByAbstractName(a, "Symbol")).Where(e => e.SymbolKind.HasValue).Select(e => e.SymbolKind.Value).Distinct();
AssertSequenceEqual(expectedSymbolKinds, actualSymbolKinds);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册