|
8 | 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; |
9 | 9 | using Microsoft.CodeAnalysis.CSharp.Test.Utilities; |
10 | 10 | using Microsoft.CodeAnalysis.Diagnostics; |
| 11 | +using Microsoft.CodeAnalysis.Operations; |
11 | 12 | using Microsoft.CodeAnalysis.Test.Utilities; |
12 | 13 | using Roslyn.Test.Utilities; |
13 | 14 | using System.Collections.Immutable; |
@@ -12710,5 +12711,154 @@ public partial class Class1 |
12710 | 12711 | var comp = CreateCompilation([source1, source2]); |
12711 | 12712 | comp.VerifyEmitDiagnostics(); |
12712 | 12713 | } |
| 12714 | + |
| 12715 | + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/79201")] |
| 12716 | + [InlineData("""get { return field + "a"; }""")] |
| 12717 | + [InlineData("""get => field + "a";""")] |
| 12718 | + public void PublicAPI_01(string accessor) |
| 12719 | + { |
| 12720 | + var source = $$""" |
| 12721 | + class C |
| 12722 | + { |
| 12723 | + public string Prop |
| 12724 | + { |
| 12725 | + {{accessor}} |
| 12726 | + } |
| 12727 | + } |
| 12728 | + """; |
| 12729 | + |
| 12730 | + var comp = CreateCompilation(source); |
| 12731 | + comp.VerifyEmitDiagnostics(); |
| 12732 | + |
| 12733 | + var tree = comp.SyntaxTrees[0]; |
| 12734 | + var model = comp.GetSemanticModel(tree); |
| 12735 | + var fieldExpression = tree.GetRoot().DescendantNodes().OfType<FieldExpressionSyntax>().Single(); |
| 12736 | + |
| 12737 | + var symbolInfo = model.GetSymbolInfo(fieldExpression); |
| 12738 | + Assert.Equal("System.String C.<Prop>k__BackingField", symbolInfo.Symbol.ToTestDisplayString()); |
| 12739 | + } |
| 12740 | + |
| 12741 | + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/79201")] |
| 12742 | + [InlineData("""set { field = value; }""")] |
| 12743 | + [InlineData("""set => field = value;""")] |
| 12744 | + public void PublicAPI_02(string accessor) |
| 12745 | + { |
| 12746 | + var source = $$""" |
| 12747 | + class C |
| 12748 | + { |
| 12749 | + public string Prop |
| 12750 | + { |
| 12751 | + {{accessor}} |
| 12752 | + } |
| 12753 | + } |
| 12754 | + """; |
| 12755 | + |
| 12756 | + var comp = CreateCompilation(source); |
| 12757 | + comp.VerifyEmitDiagnostics(); |
| 12758 | + |
| 12759 | + var tree = comp.SyntaxTrees[0]; |
| 12760 | + var model = comp.GetSemanticModel(tree); |
| 12761 | + var fieldExpression = tree.GetRoot().DescendantNodes().OfType<FieldExpressionSyntax>().Single(); |
| 12762 | + |
| 12763 | + var symbolInfo = model.GetSymbolInfo(fieldExpression); |
| 12764 | + Assert.Equal("System.String C.<Prop>k__BackingField", symbolInfo.Symbol.ToTestDisplayString()); |
| 12765 | + } |
| 12766 | + |
| 12767 | + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79201")] |
| 12768 | + public void PublicAPI_03() |
| 12769 | + { |
| 12770 | + var source = $$""" |
| 12771 | + class C |
| 12772 | + { |
| 12773 | + public string Prop |
| 12774 | + { |
| 12775 | + get => field; |
| 12776 | + } |
| 12777 | + } |
| 12778 | + """; |
| 12779 | + |
| 12780 | + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular13); |
| 12781 | + comp.VerifyEmitDiagnostics( |
| 12782 | + // (5,16): error CS0103: The name 'field' does not exist in the current context |
| 12783 | + // get => field; |
| 12784 | + Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(5, 16)); |
| 12785 | + |
| 12786 | + var tree = comp.SyntaxTrees[0]; |
| 12787 | + var model = comp.GetSemanticModel(tree); |
| 12788 | + Assert.Empty(tree.GetRoot().DescendantNodes().OfType<FieldExpressionSyntax>()); |
| 12789 | + var fieldExpression = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(node => node.ToString() == "field").Single(); |
| 12790 | + var symbolInfo = model.GetSymbolInfo(fieldExpression); |
| 12791 | + Assert.Null(symbolInfo.Symbol); |
| 12792 | + } |
| 12793 | + |
| 12794 | + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79201")] |
| 12795 | + public void PublicAPI_04() |
| 12796 | + { |
| 12797 | + var source = $$""" |
| 12798 | + class C |
| 12799 | + { |
| 12800 | + public string Prop |
| 12801 | + { |
| 12802 | + get => field; |
| 12803 | + } |
| 12804 | + } |
| 12805 | + """; |
| 12806 | + |
| 12807 | + var comp = CreateCompilation(source); |
| 12808 | + comp.VerifyEmitDiagnostics(); |
| 12809 | + comp.VerifyAnalyzerDiagnostics(analyzers: [new TestAnalyzer1()], |
| 12810 | + expected: [Diagnostic("TEST_Field", "field").WithLocation(5, 16)]); |
| 12811 | + |
| 12812 | + comp = CreateCompilation(source, parseOptions: TestOptions.Regular13); |
| 12813 | + comp.VerifyEmitDiagnostics( |
| 12814 | + // (5,16): error CS0103: The name 'field' does not exist in the current context |
| 12815 | + // get => field; |
| 12816 | + Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(5, 16)); |
| 12817 | + comp.VerifyAnalyzerDiagnostics(analyzers: [new TestAnalyzer1()], |
| 12818 | + expected: [Diagnostic("TEST_Invalid", "field").WithLocation(5, 16)]); |
| 12819 | + } |
| 12820 | + |
| 12821 | + private class TestAnalyzer1 : DiagnosticAnalyzer |
| 12822 | + { |
| 12823 | + public static readonly DiagnosticDescriptor Descriptor_Field = new(id: "TEST_Field", title: "Test", messageFormat: "", category: "", DiagnosticSeverity.Warning, isEnabledByDefault: true); |
| 12824 | + public static readonly DiagnosticDescriptor Descriptor_Invalid = new(id: "TEST_Invalid", title: "Test", messageFormat: "", category: "", DiagnosticSeverity.Warning, isEnabledByDefault: true); |
| 12825 | + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Descriptor_Field, Descriptor_Invalid]; |
| 12826 | + |
| 12827 | + public override void Initialize(AnalysisContext context) |
| 12828 | + { |
| 12829 | + context.RegisterOperationBlockAction(context => |
| 12830 | + { |
| 12831 | + foreach (var block in context.OperationBlocks) |
| 12832 | + { |
| 12833 | + var walker = new OperationWalker1(); |
| 12834 | + walker.Visit(block); |
| 12835 | + |
| 12836 | + if (walker.FieldReference is not null) |
| 12837 | + context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor_Field, walker.FieldReference.Syntax.Location)); |
| 12838 | + |
| 12839 | + if (walker.Invalid is not null) |
| 12840 | + context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor_Invalid, walker.Invalid.Syntax.Location)); |
| 12841 | + } |
| 12842 | + }); |
| 12843 | + } |
| 12844 | + } |
| 12845 | + |
| 12846 | + private class OperationWalker1 : OperationWalker |
| 12847 | + { |
| 12848 | + public IOperation FieldReference = null; |
| 12849 | + public IOperation Invalid = null; |
| 12850 | + |
| 12851 | + public override void VisitFieldReference(IFieldReferenceOperation operation) |
| 12852 | + { |
| 12853 | + FieldReference = operation; |
| 12854 | + base.VisitFieldReference(operation); |
| 12855 | + } |
| 12856 | + |
| 12857 | + public override void VisitInvalid(IInvalidOperation operation) |
| 12858 | + { |
| 12859 | + Invalid = operation; |
| 12860 | + base.VisitInvalid(operation); |
| 12861 | + } |
| 12862 | + } |
12713 | 12863 | } |
12714 | 12864 | } |
0 commit comments