|
5 | 5 |
|
6 | 6 | using System; |
7 | 7 | using System.Collections; |
| 8 | +using System.Collections.Concurrent; |
8 | 9 | using System.Collections.Generic; |
| 10 | +using System.Collections.Immutable; |
9 | 11 | using System.Linq; |
10 | 12 | using Microsoft.CodeAnalysis.CSharp.Symbols; |
11 | 13 | using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; |
12 | 14 | using Microsoft.CodeAnalysis.CSharp.Syntax; |
13 | 15 | using Microsoft.CodeAnalysis.CSharp.Test.Utilities; |
| 16 | +using Microsoft.CodeAnalysis.Diagnostics; |
14 | 17 | using Microsoft.CodeAnalysis.Emit; |
15 | 18 | using Microsoft.CodeAnalysis.Test.Utilities; |
16 | 19 | using Microsoft.CodeAnalysis.VisualBasic; |
@@ -37287,4 +37290,237 @@ static class E |
37287 | 37290 | var model = comp.GetSemanticModel(tree); |
37288 | 37291 | Assert.Equal(["(T, null)", "(T, T)"], PrintXmlNameSymbols(tree, model)); |
37289 | 37292 | } |
| 37293 | + |
| 37294 | + [Fact] |
| 37295 | + public void AnalyzerActions_01() |
| 37296 | + { |
| 37297 | + var src = """ |
| 37298 | +static class E |
| 37299 | +{ |
| 37300 | + extension<T>([Attr] T t) |
| 37301 | + { |
| 37302 | + [Attr2] |
| 37303 | + public void M() { } |
| 37304 | + |
| 37305 | + [Attr3] |
| 37306 | + public int P => 0; |
| 37307 | + } |
| 37308 | +} |
| 37309 | +"""; |
| 37310 | + |
| 37311 | + var analyzer = new AnalyzerActions_01_Analyzer(); |
| 37312 | + var comp = CreateCompilation(src); |
| 37313 | + comp.GetAnalyzerDiagnostics([analyzer], null).Verify(); |
| 37314 | + |
| 37315 | + AssertEx.SetEqual([ |
| 37316 | + "Attr2 -> void E.<>E__0<T>.M()", |
| 37317 | + "M -> void E.<>E__0<T>.M()", |
| 37318 | + "Attr3 -> System.Int32 E.<>E__0<T>.P { get; }", |
| 37319 | + "P -> System.Int32 E.<>E__0<T>.P { get; }", |
| 37320 | + "T -> E.<>E__0<T>", |
| 37321 | + "Attr -> E.<>E__0<T>", |
| 37322 | + "extension -> E.<>E__0<T>"], |
| 37323 | + analyzer._results.ToArray()); |
| 37324 | + } |
| 37325 | + |
| 37326 | + private class AnalyzerActions_01_Analyzer : DiagnosticAnalyzer |
| 37327 | + { |
| 37328 | + public ConcurrentQueue<string> _results = new ConcurrentQueue<string>(); |
| 37329 | + |
| 37330 | + private static readonly DiagnosticDescriptor Descriptor = |
| 37331 | + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); |
| 37332 | + |
| 37333 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor]; |
| 37334 | + |
| 37335 | + public override void Initialize(AnalysisContext context) |
| 37336 | + { |
| 37337 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.ExtensionDeclaration); |
| 37338 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.IdentifierName); |
| 37339 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.MethodDeclaration); |
| 37340 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.PropertyDeclaration); |
| 37341 | + |
| 37342 | + void handle(SyntaxNodeAnalysisContext context) |
| 37343 | + { |
| 37344 | + _results.Enqueue(print(context)); |
| 37345 | + Assert.Same(context.Node.SyntaxTree, context.ContainingSymbol!.DeclaringSyntaxReferences.Single().SyntaxTree); |
| 37346 | + } |
| 37347 | + |
| 37348 | + static string print(SyntaxNodeAnalysisContext context) |
| 37349 | + { |
| 37350 | + var syntaxString = context.Node switch |
| 37351 | + { |
| 37352 | + ExtensionDeclarationSyntax => "extension", |
| 37353 | + MethodDeclarationSyntax method => method.Identifier.ValueText, |
| 37354 | + PropertyDeclarationSyntax property => property.Identifier.ValueText, |
| 37355 | + _ => context.Node.ToString() |
| 37356 | + }; |
| 37357 | + |
| 37358 | + return $"{syntaxString} -> {context.ContainingSymbol.ToTestDisplayString()}"; |
| 37359 | + } |
| 37360 | + } |
| 37361 | + } |
| 37362 | + |
| 37363 | + [Fact] |
| 37364 | + public void AnalyzerActions_02() |
| 37365 | + { |
| 37366 | + var src = """ |
| 37367 | +static class E |
| 37368 | +{ |
| 37369 | + extension<T>(T t) |
| 37370 | + { |
| 37371 | + public void M(int i) { } |
| 37372 | + public int P => 0; |
| 37373 | + } |
| 37374 | + extension(__arglist) { } |
| 37375 | + extension(object o1, object o2) { } |
| 37376 | +} |
| 37377 | +"""; |
| 37378 | + |
| 37379 | + var analyzer = new AnalyzerActions_02_Analyzer(); |
| 37380 | + var comp = CreateCompilation(src); |
| 37381 | + comp.GetAnalyzerDiagnostics([analyzer], null).Verify(); |
| 37382 | + |
| 37383 | + AssertEx.SetEqual([ |
| 37384 | + "E", |
| 37385 | + "E.<>E__0<T>", |
| 37386 | + "System.Int32 E.<>E__0<T>.P { get; }", |
| 37387 | + "T t", |
| 37388 | + "E.<>E__1", |
| 37389 | + "E.<>E__2", |
| 37390 | + "System.Object o1", |
| 37391 | + "void E.<>E__0<T>.M(System.Int32 i)", |
| 37392 | + "System.Int32 i", |
| 37393 | + "System.Int32 E.<>E__0<T>.P.get"], |
| 37394 | + analyzer._results.ToArray()); |
| 37395 | + } |
| 37396 | + |
| 37397 | + private class AnalyzerActions_02_Analyzer : DiagnosticAnalyzer |
| 37398 | + { |
| 37399 | + public ConcurrentQueue<string> _results = new ConcurrentQueue<string>(); |
| 37400 | + |
| 37401 | + private static readonly DiagnosticDescriptor Descriptor = |
| 37402 | + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); |
| 37403 | + |
| 37404 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor]; |
| 37405 | + |
| 37406 | + public override void Initialize(AnalysisContext context) |
| 37407 | + { |
| 37408 | + context.RegisterSymbolAction(handle, SymbolKind.NamedType); |
| 37409 | + context.RegisterSymbolAction(handle, SymbolKind.Parameter); |
| 37410 | + context.RegisterSymbolAction(handle, SymbolKind.TypeParameter); |
| 37411 | + context.RegisterSymbolAction(handle, SymbolKind.Method); |
| 37412 | + context.RegisterSymbolAction(handle, SymbolKind.Property); |
| 37413 | + |
| 37414 | + void handle(SymbolAnalysisContext context) |
| 37415 | + { |
| 37416 | + _results.Enqueue(context.Symbol.ToTestDisplayString()); |
| 37417 | + } |
| 37418 | + } |
| 37419 | + } |
| 37420 | + |
| 37421 | + [Fact] |
| 37422 | + public void AnalyzerActions_03() |
| 37423 | + { |
| 37424 | + var src = """ |
| 37425 | +static class E |
| 37426 | +{ |
| 37427 | + extension<T>(T t) |
| 37428 | + { |
| 37429 | + public void M() { } |
| 37430 | + public int P { get { return 0; } } |
| 37431 | + } |
| 37432 | +} |
| 37433 | +"""; |
| 37434 | + |
| 37435 | + var analyzer = new AnalyzerActions_03_Analyzer(); |
| 37436 | + var comp = CreateCompilation(src); |
| 37437 | + comp.GetAnalyzerDiagnostics([analyzer], null).Verify(); |
| 37438 | + |
| 37439 | + AssertEx.SetEqual([ |
| 37440 | + "public void M() { } -> void E.<>E__0<T>.M()", |
| 37441 | + "get { return 0; } -> System.Int32 E.<>E__0<T>.P.get"], |
| 37442 | + analyzer._results.ToArray()); |
| 37443 | + } |
| 37444 | + |
| 37445 | + private class AnalyzerActions_03_Analyzer : DiagnosticAnalyzer |
| 37446 | + { |
| 37447 | + public ConcurrentQueue<string> _results = new ConcurrentQueue<string>(); |
| 37448 | + |
| 37449 | + private static readonly DiagnosticDescriptor Descriptor = |
| 37450 | + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); |
| 37451 | + |
| 37452 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor]; |
| 37453 | + |
| 37454 | + public override void Initialize(AnalysisContext context) |
| 37455 | + { |
| 37456 | + context.RegisterOperationAction(handle, OperationKind.MethodBody); |
| 37457 | + |
| 37458 | + void handle(OperationAnalysisContext context) |
| 37459 | + { |
| 37460 | + _results.Enqueue($"{context.Operation.Syntax.ToString()} -> {context.ContainingSymbol.ToTestDisplayString()}"); |
| 37461 | + } |
| 37462 | + } |
| 37463 | + } |
| 37464 | + |
| 37465 | + [Fact] |
| 37466 | + public void AnalyzerActions_04() |
| 37467 | + { |
| 37468 | + var src = """ |
| 37469 | +static class E |
| 37470 | +{ |
| 37471 | + extension<T>(T t) |
| 37472 | + { |
| 37473 | + public void M(int i) { } |
| 37474 | + public int P { get { return 0; } } |
| 37475 | + } |
| 37476 | +} |
| 37477 | +"""; |
| 37478 | + |
| 37479 | + var analyzer = new AnalyzerActions_04_Analyzer(); |
| 37480 | + var comp = CreateCompilation(src); |
| 37481 | + comp.GetAnalyzerDiagnostics([analyzer], null).Verify(); |
| 37482 | + |
| 37483 | + AssertEx.SetEqual([ |
| 37484 | + "Start: E", |
| 37485 | + "Start: E.<>E__0<T>", |
| 37486 | + "Start: void E.<>E__0<T>.M(System.Int32 i)", |
| 37487 | + "Start: System.Int32 E.<>E__0<T>.P { get; }", |
| 37488 | + "Start: System.Int32 E.<>E__0<T>.P.get", |
| 37489 | + "End: System.Int32 E.<>E__0<T>.P { get; }", |
| 37490 | + "End: System.Int32 E.<>E__0<T>.P.get", |
| 37491 | + "End: void E.<>E__0<T>.M(System.Int32 i)", |
| 37492 | + "End: E.<>E__0<T>", |
| 37493 | + "End: E"], |
| 37494 | + analyzer._results.ToArray()); |
| 37495 | + } |
| 37496 | + |
| 37497 | + private class AnalyzerActions_04_Analyzer : DiagnosticAnalyzer |
| 37498 | + { |
| 37499 | + public ConcurrentQueue<string> _results = new ConcurrentQueue<string>(); |
| 37500 | + |
| 37501 | + private static readonly DiagnosticDescriptor Descriptor = |
| 37502 | + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); |
| 37503 | + |
| 37504 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor]; |
| 37505 | + |
| 37506 | + public override void Initialize(AnalysisContext context) |
| 37507 | + { |
| 37508 | + context.RegisterSymbolStartAction(handleStart, SymbolKind.NamedType); |
| 37509 | + context.RegisterSymbolStartAction(handleStart, SymbolKind.Method); |
| 37510 | + context.RegisterSymbolStartAction(handleStart, SymbolKind.Property); |
| 37511 | + context.RegisterSymbolStartAction(handleStart, SymbolKind.Parameter); |
| 37512 | + context.RegisterSymbolStartAction(handleStart, SymbolKind.TypeParameter); |
| 37513 | + |
| 37514 | + void handleStart(SymbolStartAnalysisContext context) |
| 37515 | + { |
| 37516 | + _results.Enqueue($"Start: {context.Symbol.ToTestDisplayString()}"); |
| 37517 | + context.RegisterSymbolEndAction(handleEnd); |
| 37518 | + } |
| 37519 | + |
| 37520 | + void handleEnd(SymbolAnalysisContext context) |
| 37521 | + { |
| 37522 | + _results.Enqueue($"End: {context.Symbol.ToTestDisplayString()}"); |
| 37523 | + } |
| 37524 | + } |
| 37525 | + } |
37290 | 37526 | } |
0 commit comments