|
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; |
@@ -36601,4 +36604,166 @@ static unsafe class E |
36601 | 36604 | Assert.False(verifier.HasLocalsInit("E.M")); |
36602 | 36605 | Assert.True(verifier.HasLocalsInit("E.M2")); |
36603 | 36606 | } |
| 36607 | + |
| 36608 | + [Fact] |
| 36609 | + public void AnalyzerActions_01() |
| 36610 | + { |
| 36611 | + var src = """ |
| 36612 | +static class E |
| 36613 | +{ |
| 36614 | + extension<T>([Attr] T t) |
| 36615 | + { |
| 36616 | + [Attr2] |
| 36617 | + public void M() { } |
| 36618 | + |
| 36619 | + [Attr3] |
| 36620 | + public int P => 0; |
| 36621 | + } |
| 36622 | +} |
| 36623 | +"""; |
| 36624 | + |
| 36625 | + var analyzer = new AnalyzerActions_01_Analyzer(); |
| 36626 | + var comp = CreateCompilation(src); |
| 36627 | + comp.GetAnalyzerDiagnostics([analyzer], null).Verify(); |
| 36628 | + |
| 36629 | + AssertEx.SetEqual([ |
| 36630 | + "Attr2 -> void E.<>E__0<T>.M()", |
| 36631 | + "M -> void E.<>E__0<T>.M()", |
| 36632 | + "Attr3 -> System.Int32 E.<>E__0<T>.P { get; }", |
| 36633 | + "P -> System.Int32 E.<>E__0<T>.P { get; }", |
| 36634 | + "T -> E.<>E__0<T>", |
| 36635 | + "Attr -> E.<>E__0<T>", |
| 36636 | + "extension -> E.<>E__0<T>"], |
| 36637 | + analyzer._results.ToArray()); |
| 36638 | + } |
| 36639 | + |
| 36640 | + private class AnalyzerActions_01_Analyzer : DiagnosticAnalyzer |
| 36641 | + { |
| 36642 | + public ConcurrentQueue<string> _results = new ConcurrentQueue<string>(); |
| 36643 | + |
| 36644 | + private static readonly DiagnosticDescriptor Descriptor = |
| 36645 | + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); |
| 36646 | + |
| 36647 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor]; |
| 36648 | + |
| 36649 | + public override void Initialize(AnalysisContext context) |
| 36650 | + { |
| 36651 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.ExtensionDeclaration); |
| 36652 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.IdentifierName); |
| 36653 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.MethodDeclaration); |
| 36654 | + context.RegisterSyntaxNodeAction(handle, SyntaxKind.PropertyDeclaration); |
| 36655 | + |
| 36656 | + void handle(SyntaxNodeAnalysisContext context) |
| 36657 | + { |
| 36658 | + _results.Enqueue(print(context)); |
| 36659 | + Assert.Same(context.Node.SyntaxTree, context.ContainingSymbol!.DeclaringSyntaxReferences.Single().SyntaxTree); |
| 36660 | + } |
| 36661 | + |
| 36662 | + static string print(SyntaxNodeAnalysisContext context) |
| 36663 | + { |
| 36664 | + var syntaxString = context.Node switch |
| 36665 | + { |
| 36666 | + ExtensionDeclarationSyntax => "extension", |
| 36667 | + MethodDeclarationSyntax method => method.Identifier.ValueText, |
| 36668 | + PropertyDeclarationSyntax property => property.Identifier.ValueText, |
| 36669 | + _ => context.Node.ToString() |
| 36670 | + }; |
| 36671 | + |
| 36672 | + return $"{syntaxString} -> {context.ContainingSymbol.ToTestDisplayString()}"; |
| 36673 | + } |
| 36674 | + } |
| 36675 | + } |
| 36676 | + |
| 36677 | + [Fact] |
| 36678 | + public void AnalyzerActions_02() |
| 36679 | + { |
| 36680 | + var src = """ |
| 36681 | +static class E |
| 36682 | +{ |
| 36683 | + extension<T>(T t) |
| 36684 | + { |
| 36685 | + public void M() { } |
| 36686 | + public int P => 0; |
| 36687 | + } |
| 36688 | +} |
| 36689 | +"""; |
| 36690 | + |
| 36691 | + var analyzer = new AnalyzerActions_02_Analyzer(); |
| 36692 | + var comp = CreateCompilation(src); |
| 36693 | + comp.GetAnalyzerDiagnostics([analyzer], null).Verify(); |
| 36694 | + |
| 36695 | + AssertEx.SetEqual([ |
| 36696 | + "System.Int32 E.<>E__0<T>.P.get", |
| 36697 | + "void E.<>E__0<T>.M()", |
| 36698 | + "E.<>E__0<T>", |
| 36699 | + "System.Int32 E.<>E__0<T>.P { get; }", |
| 36700 | + "E"], |
| 36701 | + analyzer._results.ToArray()); |
| 36702 | + } |
| 36703 | + |
| 36704 | + private class AnalyzerActions_02_Analyzer : DiagnosticAnalyzer |
| 36705 | + { |
| 36706 | + public ConcurrentQueue<string> _results = new ConcurrentQueue<string>(); |
| 36707 | + |
| 36708 | + private static readonly DiagnosticDescriptor Descriptor = |
| 36709 | + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); |
| 36710 | + |
| 36711 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor]; |
| 36712 | + |
| 36713 | + public override void Initialize(AnalysisContext context) |
| 36714 | + { |
| 36715 | + context.RegisterSymbolAction(handle, SymbolKind.NamedType); |
| 36716 | + context.RegisterSymbolAction(handle, SymbolKind.Method); |
| 36717 | + context.RegisterSymbolAction(handle, SymbolKind.Property); |
| 36718 | + |
| 36719 | + void handle(SymbolAnalysisContext context) |
| 36720 | + { |
| 36721 | + _results.Enqueue(context.Symbol.ToTestDisplayString()); |
| 36722 | + } |
| 36723 | + } |
| 36724 | + } |
| 36725 | + |
| 36726 | + [Fact] |
| 36727 | + public void AnalyzerActions_03() |
| 36728 | + { |
| 36729 | + var src = """ |
| 36730 | +static class E |
| 36731 | +{ |
| 36732 | + extension<T>(T t) |
| 36733 | + { |
| 36734 | + public void M() { } |
| 36735 | + public int P { get { return 0; } } |
| 36736 | + } |
| 36737 | +} |
| 36738 | +"""; |
| 36739 | + |
| 36740 | + var analyzer = new AnalyzerActions_03_Analyzer(); |
| 36741 | + var comp = CreateCompilation(src); |
| 36742 | + comp.GetAnalyzerDiagnostics([analyzer], null).Verify(); |
| 36743 | + |
| 36744 | + AssertEx.SetEqual([ |
| 36745 | + "public void M() { } -> void E.<>E__0<T>.M()", |
| 36746 | + "get { return 0; } -> System.Int32 E.<>E__0<T>.P.get"], |
| 36747 | + analyzer._results.ToArray()); |
| 36748 | + } |
| 36749 | + |
| 36750 | + private class AnalyzerActions_03_Analyzer : DiagnosticAnalyzer |
| 36751 | + { |
| 36752 | + public ConcurrentQueue<string> _results = new ConcurrentQueue<string>(); |
| 36753 | + |
| 36754 | + private static readonly DiagnosticDescriptor Descriptor = |
| 36755 | + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); |
| 36756 | + |
| 36757 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor]; |
| 36758 | + |
| 36759 | + public override void Initialize(AnalysisContext context) |
| 36760 | + { |
| 36761 | + context.RegisterOperationAction(handle, OperationKind.MethodBody); |
| 36762 | + |
| 36763 | + void handle(OperationAnalysisContext context) |
| 36764 | + { |
| 36765 | + _results.Enqueue($"{context.Operation.Syntax.ToString()} -> {context.ContainingSymbol.ToTestDisplayString()}"); |
| 36766 | + } |
| 36767 | + } |
| 36768 | + } |
36604 | 36769 | } |
0 commit comments