diff --git a/src/Compilers/CSharp/Portable/Symbols/PublicModel/EventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PublicModel/EventSymbol.cs index fa4cbbb5d08e6..1c70ed3dada65 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PublicModel/EventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PublicModel/EventSymbol.cs @@ -62,6 +62,14 @@ ITypeSymbol IEventSymbol.Type } } + IFieldSymbol? IEventSymbol.BackingField + { + get + { + return _underlying.AssociatedField.GetPublicSymbol(); + } + } + IEventSymbol IEventSymbol.OriginalDefinition { get diff --git a/src/Compilers/CSharp/Portable/Symbols/PublicModel/PropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PublicModel/PropertySymbol.cs index bd74b98ea0dc3..605bf7194ab1c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PublicModel/PropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PublicModel/PropertySymbol.cs @@ -58,6 +58,11 @@ IMethodSymbol IPropertySymbol.SetMethod get { return _underlying.SetMethod.GetPublicSymbol(); } } + IFieldSymbol IPropertySymbol.BackingField + { + get { return (_underlying as SourcePropertySymbolBase)?.BackingField.GetPublicSymbol(); } + } + IPropertySymbol IPropertySymbol.OriginalDefinition { get diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs index 18456ec62555c..5fa2e26804548 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs @@ -360,6 +360,8 @@ public void TestGetDeclaredSymbolFromIndexer() Assert.Equal(MethodKind.PropertySet, setterSymbol.MethodKind); Assert.Equal(propertySymbol.SetMethod, setterSymbol); Assert.Equal("void C.this[System.Int32 x, System.Int32 y].set", setterSymbol.ToTestDisplayString()); + + Assert.Null(propertySymbol.BackingField); } [Fact] @@ -389,6 +391,7 @@ event System.Action E Assert.Equal(2, accessorList.Count); Assert.Same(eventSymbol.AddMethod, model.GetDeclaredSymbol(accessorList[0])); Assert.Same(eventSymbol.RemoveMethod, model.GetDeclaredSymbol(accessorList[1])); + Assert.Null(eventSymbol.BackingField); } [WorkItem(543494, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543494")] @@ -406,11 +409,13 @@ public void TestGetDeclaredSymbolFromFieldLikeEvent() var typeDecl = (TypeDeclarationSyntax)root.Members[0]; var eventDecl = (EventFieldDeclarationSyntax)typeDecl.Members[0]; var model = compilation.GetSemanticModel(tree); - var eventSymbol = model.GetDeclaredSymbol(eventDecl.Declaration.Variables[0]); + var eventSymbol = (IEventSymbol)model.GetDeclaredSymbol(eventDecl.Declaration.Variables[0]); Assert.NotNull(eventSymbol); Assert.Null(model.GetDeclaredSymbol(eventDecl)); // the event decl may have multiple variable declarators, the result for GetDeclaredSymbol will always be null Assert.Equal("E", eventSymbol.Name); Assert.IsType(eventSymbol.GetSymbol()); + Assert.NotNull(eventSymbol.BackingField); + Assert.Equal(eventSymbol, eventSymbol.BackingField.AssociatedSymbol); } [WorkItem(543574, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543574")] @@ -2883,6 +2888,8 @@ void I.M() {} Assert.Equal("I.set_P", explicitPropertySetterSymbol.Name); Assert.Equal(1, explicitPropertySetterSymbol.ExplicitInterfaceImplementations.Length); Assert.Same(explicitPropertySymbol.SetMethod, explicitPropertySetterSymbol); + + Assert.NotNull(explicitPropertySymbol.BackingField); } [WorkItem(527284, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527284")] diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 41853b3182167..f2718964ba2c5 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -1,5 +1,7 @@ Microsoft.CodeAnalysis.GeneratorAttribute.GeneratorAttribute(string firstLanguage, params string[] additionalLanguages) -> void Microsoft.CodeAnalysis.GeneratorAttribute.Languages.get -> string[] +Microsoft.CodeAnalysis.IEventSymbol.BackingField.get -> Microsoft.CodeAnalysis.IFieldSymbol +Microsoft.CodeAnalysis.IPropertySymbol.BackingField.get -> Microsoft.CodeAnalysis.IFieldSymbol Microsoft.CodeAnalysis.ITypeSymbol.IsRecord.get -> bool Microsoft.CodeAnalysis.SymbolDisplayPartKind.RecordName = 31 -> Microsoft.CodeAnalysis.SymbolDisplayPartKind const Microsoft.CodeAnalysis.WellKnownDiagnosticTags.CompilationEnd = "CompilationEnd" -> string diff --git a/src/Compilers/Core/Portable/Symbols/IEventSymbol.cs b/src/Compilers/Core/Portable/Symbols/IEventSymbol.cs index 962e396bec592..5063ad09bda30 100644 --- a/src/Compilers/Core/Portable/Symbols/IEventSymbol.cs +++ b/src/Compilers/Core/Portable/Symbols/IEventSymbol.cs @@ -46,6 +46,11 @@ public interface IEventSymbol : ISymbol /// IMethodSymbol? RaiseMethod { get; } + /// + /// The backing field of the event, or null if the event does not use a backing field. + /// + IFieldSymbol? BackingField { get; } + /// /// The original definition of the event. If the event is constructed from another /// symbol by type substitution, OriginalDefinition gets the original symbol, as it was diff --git a/src/Compilers/Core/Portable/Symbols/IPropertySymbol.cs b/src/Compilers/Core/Portable/Symbols/IPropertySymbol.cs index bd40a5adcbc5f..e6dfcbc69e361 100644 --- a/src/Compilers/Core/Portable/Symbols/IPropertySymbol.cs +++ b/src/Compilers/Core/Portable/Symbols/IPropertySymbol.cs @@ -76,6 +76,11 @@ public interface IPropertySymbol : ISymbol /// IMethodSymbol? SetMethod { get; } + /// + /// The backing field of the property, or null if the property does not use a backing field. + /// + IFieldSymbol? BackingField { get; } + /// /// The original definition of the property. If the property is constructed from another /// symbol by type substitution, OriginalDefinition gets the original symbol, as it was diff --git a/src/Compilers/VisualBasic/Portable/Symbols/EventSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/EventSymbol.vb index b1d7a169a882b..cee2dcc647c28 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/EventSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/EventSymbol.vb @@ -302,6 +302,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Private ReadOnly Property IEventSymbol_BackingField As IFieldSymbol Implements IEventSymbol.BackingField + Get + Return Me.AssociatedField + End Get + End Property + Private ReadOnly Property IEventSymbol_OriginalDefinition As IEventSymbol Implements IEventSymbol.OriginalDefinition Get Return Me.OriginalDefinition diff --git a/src/Compilers/VisualBasic/Portable/Symbols/PropertySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/PropertySymbol.vb index c368d824437e5..9117c71cba062 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/PropertySymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/PropertySymbol.vb @@ -503,6 +503,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Private ReadOnly Property IPropertySymbol_BackingField As IFieldSymbol Implements IPropertySymbol.BackingField + Get + Return Me.AssociatedField + End Get + End Property + Private ReadOnly Property IPropertySymbol_ReturnsByRef As Boolean Implements IPropertySymbol.ReturnsByRef Get Return Me.ReturnsByRef diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb index 0e1824082fbbb..e991f4be1d74c 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb @@ -1098,9 +1098,12 @@ End Class propertySymbol = GetPropertySymbol(compilation, bindings, "c.vb", "Property P As Integer", propertySyntax) Assert.NotNull(propertySymbol) + Assert.Null(propertySymbol.BackingField) propertySymbol = GetPropertySymbol(compilation, bindings, "c.vb", "Property Q As Object", propertySyntax) Assert.NotNull(propertySymbol) + Assert.NotNull(propertySymbol.BackingField) + Assert.Equal(propertySymbol, propertySymbol.BackingField.AssociatedSymbol) propertySymbol = GetPropertySymbol(compilation, bindings, "c.vb", "Property R(index As Integer)", propertySyntax) Assert.NotNull(propertySymbol) diff --git a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedEventSymbol.cs b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedEventSymbol.cs index e07d4f0a289d5..b584b6b210a08 100644 --- a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedEventSymbol.cs +++ b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedEventSymbol.cs @@ -36,6 +36,7 @@ public ImmutableArray ExplicitInterfaceImplementations public IEventSymbol? OverriddenEvent => _symbol.OverriddenEvent; public IMethodSymbol? RaiseMethod => _symbol.RaiseMethod; public IMethodSymbol? RemoveMethod => _symbol.RemoveMethod; + public IFieldSymbol? BackingField => _symbol.BackingField; public ITypeSymbol Type => _symbol.Type; public NullableAnnotation NullableAnnotation => _symbol.NullableAnnotation; } diff --git a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedPropertySymbol.cs b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedPropertySymbol.cs index e3746247a0d2b..9c46b25e81a67 100644 --- a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedPropertySymbol.cs +++ b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedPropertySymbol.cs @@ -53,6 +53,8 @@ public ImmutableArray ExplicitInterfaceImplementations public IMethodSymbol SetMethod => _symbol.SetMethod; + public IFieldSymbol BackingField => _symbol.BackingField; + public ITypeSymbol Type => _symbol.Type; public NullableAnnotation NullableAnnotation => _symbol.NullableAnnotation; diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationEventSymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationEventSymbol.cs index 7b7949f8b12d3..3b7fbbf0e6b64 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationEventSymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationEventSymbol.cs @@ -62,5 +62,7 @@ public override void Accept(SymbolVisitor visitor) public IEventSymbol? OverriddenEvent => null; public static ImmutableArray TypeCustomModifiers => ImmutableArray.Create(); + + public IFieldSymbol BackingField => null; } } diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationPropertySymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationPropertySymbol.cs index 49b9774591c6c..a90e0a6fabb32 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationPropertySymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationPropertySymbol.cs @@ -88,5 +88,7 @@ public override TResult Accept(SymbolVisitor visitor) public ImmutableArray RefCustomModifiers => ImmutableArray.Empty; public ImmutableArray TypeCustomModifiers => ImmutableArray.Empty; + + public IFieldSymbol BackingField => null; } }