未验证 提交 b001cfaa 编写于 作者: A Andy Gocke 提交者: GitHub

Extract SourcePropertySymbolBase class (#45411)

Records need to provide a new form of source property symbol with
different syntax. This PR extracts a new base class to try to share as
much code as possible with the existing SourcePropertySymbol and the
SynthesizedRecordPropertySymbol.
上级 7a836c8e
......@@ -1621,7 +1621,7 @@ private static bool AccessingAutoPropertyFromConstructor(BoundExpression receive
propertySymbol = propertySymbol.OriginalDefinition;
}
var sourceProperty = propertySymbol as SourceOrRecordPropertySymbol;
var sourceProperty = propertySymbol as SourcePropertySymbolBase;
var propertyIsStatic = propertySymbol.IsStatic;
return (object)sourceProperty != null &&
......
......@@ -1489,7 +1489,16 @@ internal static bool ReportUseSiteDiagnostics(Symbol symbol, DiagnosticBag diagn
/// </summary>
internal NamedTypeSymbol GetWellKnownType(WellKnownType type, DiagnosticBag diagnostics, SyntaxNode node)
{
return GetWellKnownType(this.Compilation, type, diagnostics, node.Location);
return GetWellKnownType(type, diagnostics, node.Location);
}
/// <summary>
/// This is a layer on top of the Compilation version that generates a diagnostic if the well-known
/// type isn't found.
/// </summary>
internal NamedTypeSymbol GetWellKnownType(WellKnownType type, DiagnosticBag diagnostics, Location location)
{
return GetWellKnownType(this.Compilation, type, diagnostics, location);
}
/// <summary>
......
......@@ -172,7 +172,7 @@ internal static BoundBlock ConstructAutoPropertyAccessorBody(SourceMemberMethodS
{
Debug.Assert(accessor.MethodKind == MethodKind.PropertyGet || accessor.MethodKind == MethodKind.PropertySet);
var property = (SourcePropertySymbol)accessor.AssociatedSymbol;
var property = (SourcePropertySymbolBase)accessor.AssociatedSymbol;
CSharpSyntaxNode syntax = property.CSharpSyntaxNode;
BoundExpression thisReference = null;
if (!accessor.IsStatic)
......
......@@ -515,7 +515,7 @@ private void CompileNamedType(NamedTypeSymbol containingType)
case SymbolKind.Property:
{
SourcePropertySymbol sourceProperty = member as SourcePropertySymbol;
var sourceProperty = member as SourcePropertySymbolBase;
if ((object)sourceProperty != null && sourceProperty.IsSealed && compilationState.Emitting)
{
CompileSynthesizedSealedAccessors(sourceProperty, compilationState);
......@@ -797,7 +797,7 @@ private void CompileSynthesizedExplicitImplementations(SourceMemberContainerType
}
}
private void CompileSynthesizedSealedAccessors(SourcePropertySymbol sourceProperty, TypeCompilationState compilationState)
private void CompileSynthesizedSealedAccessors(SourcePropertySymbolBase sourceProperty, TypeCompilationState compilationState)
{
SynthesizedSealedPropertyAccessor synthesizedAccessor = sourceProperty.SynthesizedSealedAccessorOpt;
......@@ -1722,7 +1722,7 @@ internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSt
}
else
{
var property = sourceMethod.AssociatedSymbol as SourcePropertySymbol;
var property = sourceMethod.AssociatedSymbol as SourcePropertySymbolBase;
if ((object)property != null && property.IsAutoProperty)
{
return MethodBodySynthesizer.ConstructAutoPropertyAccessorBody(sourceMethod);
......
......@@ -91,7 +91,7 @@ public override void VisitNamedType(NamedTypeSymbol symbol)
public override void VisitProperty(PropertySymbol symbol)
{
var sourceProperty = symbol as SourcePropertySymbol;
var sourceProperty = symbol as SourcePropertySymbolBase;
if ((object)sourceProperty != null && sourceProperty.IsSealed)
{
var synthesizedAccessor = sourceProperty.SynthesizedSealedAccessorOpt;
......
......@@ -33,7 +33,7 @@ IEnumerable<IMethodReference> IPropertyDefinition.GetAccessors(EmitContext conte
yield return setMethod;
}
SourcePropertySymbol sourceProperty = this as SourcePropertySymbol;
var sourceProperty = this as SourcePropertySymbolBase;
if ((object)sourceProperty != null && sourceProperty.ShouldInclude(context))
{
SynthesizedSealedPropertyAccessor synthesizedAccessor = sourceProperty.SynthesizedSealedAccessorOpt;
......@@ -266,7 +266,7 @@ string INamedEntity.Name
private IMethodReference GetSynthesizedSealedAccessor(MethodKind targetMethodKind)
{
SourcePropertySymbol sourceProperty = this as SourcePropertySymbol;
var sourceProperty = this as SourcePropertySymbolBase;
if ((object)sourceProperty != null)
{
SynthesizedSealedPropertyAccessor synthesized = sourceProperty.SynthesizedSealedAccessorOpt;
......
......@@ -563,7 +563,7 @@ protected void VisitLvalue(BoundExpression node)
if (Binder.AccessingAutoPropertyFromConstructor(access, _symbol))
{
var backingField = (access.PropertySymbol as SourcePropertySymbol)?.BackingField;
var backingField = (access.PropertySymbol as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
VisitFieldAccessInternal(access.ReceiverOpt, backingField);
......@@ -1958,7 +1958,7 @@ public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
if (Binder.AccessingAutoPropertyFromConstructor(node, _symbol))
{
var backingField = (property as SourcePropertySymbol)?.BackingField;
var backingField = (property as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
VisitFieldAccessInternal(node.ReceiverOpt, backingField);
......
......@@ -798,7 +798,7 @@ protected override bool TryGetReceiverAndMember(BoundExpression expr, out BoundE
if (Binder.AccessingAutoPropertyFromConstructor(propAccess, this.CurrentSymbol))
{
var propSymbol = propAccess.PropertySymbol;
member = (propSymbol as SourcePropertySymbol)?.BackingField;
member = (propSymbol as SourcePropertySymbolBase)?.BackingField;
if (member is null)
{
return false;
......@@ -1023,7 +1023,7 @@ private bool IsAssigned(BoundExpression node, out int unassignedSlot)
if (Binder.AccessingAutoPropertyFromConstructor(propertyAccess, this.CurrentSymbol))
{
var property = propertyAccess.PropertySymbol;
var backingField = (property as SourcePropertySymbol)?.BackingField;
var backingField = (property as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
if (!MayRequireTracking(propertyAccess.ReceiverOpt, backingField) || IsAssigned(propertyAccess.ReceiverOpt, out unassignedSlot))
......@@ -2036,7 +2036,7 @@ public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
if (Binder.AccessingAutoPropertyFromConstructor(node, this.CurrentSymbol))
{
var property = node.PropertySymbol;
var backingField = (property as SourcePropertySymbol)?.BackingField;
var backingField = (property as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
if (MayRequireTracking(node.ReceiverOpt, backingField))
......
......@@ -7039,14 +7039,14 @@ static FlowAnalysisAnnotations getSetterAnnotations(PropertySymbol property)
{
return accessor.Parameters.Last().FlowAnalysisAnnotations;
}
if (property is SourcePropertySymbol sourceProperty)
if (property is SourcePropertySymbolBase sourceProperty)
{
return getPropertyAnnotations(sourceProperty);
}
return FlowAnalysisAnnotations.None;
}
static FlowAnalysisAnnotations getPropertyAnnotations(SourcePropertySymbol property)
static FlowAnalysisAnnotations getPropertyAnnotations(SourcePropertySymbolBase property)
{
var annotations = FlowAnalysisAnnotations.None;
if (property.HasAllowNull)
......
......@@ -300,7 +300,7 @@ private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bo
if (setMethod is null)
{
var autoProp = (SourceOrRecordPropertySymbol)property;
var autoProp = (SourcePropertySymbolBase)property;
Debug.Assert(autoProp.IsAutoProperty,
"only autoproperties can be assignable without having setters");
......
......@@ -104,7 +104,7 @@ private static bool ShouldMethodDisplayReadOnly(IMethodSymbol method, IPropertyS
}
if ((method as Symbols.PublicModel.MethodSymbol)?.UnderlyingMethodSymbol is SourcePropertyAccessorSymbol sourceAccessor &&
(propertyOpt as Symbols.PublicModel.PropertySymbol)?.UnderlyingSymbol is SourcePropertySymbol sourceProperty)
(propertyOpt as Symbols.PublicModel.PropertySymbol)?.UnderlyingSymbol is SourcePropertySymbolBase sourceProperty)
{
// only display if the accessor is explicitly readonly
return sourceAccessor.LocalDeclaredReadOnly || sourceProperty.HasReadOnlyModifier;
......
......@@ -2987,9 +2987,6 @@ private void AddSynthesizedRecordMembersIfNecessary(MembersAndInitializersBuilde
diagnostics.Add(ErrorCode.ERR_BadRecordDeclaration, paramList.Location);
}
BinderFactory binderFactory = this.DeclaringCompilation.GetBinderFactory(paramList.SyntaxTree);
var binder = binderFactory.GetBinder(paramList);
var ctor = addCtor(builder.RecordDeclarationWithParameters);
var existingOrAddedMembers = addProperties(ctor.Parameters);
addDeconstruct(ctor.Parameters, existingOrAddedMembers);
......
......@@ -566,7 +566,7 @@ private void HasBaseInterfaceDeclaringInterface(NamedTypeSymbol baseInterface, N
}
}
}
else if (property is SourcePropertySymbol sourceProperty)
else if (property is SourcePropertySymbolBase sourceProperty)
{
var isNewProperty = sourceProperty.IsNew;
CheckNonOverrideMember(property, isNewProperty, property.OverriddenOrHiddenMembers, diagnostics, out suppressAccessors);
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal abstract class SourceOrRecordPropertySymbol : PropertySymbol, IAttributeTargetSymbol
{
public Location Location { get; }
public SourceOrRecordPropertySymbol(Location location)
{
Location = location;
}
internal abstract SynthesizedBackingFieldSymbol BackingField { get; }
internal abstract bool IsAutoProperty { get; }
internal abstract bool HasPointerType { get; }
public abstract SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList { get; }
protected abstract IAttributeTargetSymbol AttributesOwner { get; }
protected abstract AttributeLocation AllowedAttributeLocations { get; }
protected abstract AttributeLocation DefaultAttributeLocation { get; }
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => AttributesOwner;
AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AllowedAttributeLocations;
AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => DefaultAttributeLocation;
}
}
......@@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
{
private readonly SourcePropertySymbol _property;
private readonly SourcePropertySymbolBase _property;
private ImmutableArray<ParameterSymbol> _lazyParameters;
private TypeWithAnnotations _lazyReturnType;
private ImmutableArray<CustomModifier> _lazyRefCustomModifiers;
......@@ -53,6 +53,10 @@ internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
out explicitInterfaceImplementations);
var methodKind = isGetMethod ? MethodKind.PropertyGet : MethodKind.PropertySet;
bool hasBody = syntax.Body is object;
bool hasExpressionBody = syntax.ExpressionBody is object;
CheckForBlockAndExpressionBody(syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
return new SourcePropertyAccessorSymbol(
containingType,
name,
......@@ -61,7 +65,12 @@ internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
explicitInterfaceImplementations,
syntax.Keyword.GetLocation(),
syntax,
hasBody,
hasExpressionBody,
isIterator: SyntaxFacts.HasYieldOperations(syntax.Body),
syntax.Modifiers,
methodKind,
syntax.Keyword.IsKind(SyntaxKind.InitKeyword),
isAutoPropertyAccessor,
isExplicitInterfaceImplementation,
diagnostics);
......@@ -102,6 +111,50 @@ internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
diagnostics);
}
#nullable enable
public static SourcePropertyAccessorSymbol CreateAccessorSymbol(
bool isGetMethod,
bool usesInit,
NamedTypeSymbol containingType,
SynthesizedRecordPropertySymbol property,
DeclarationModifiers propertyModifiers,
string propertyName,
Location location,
CSharpSyntaxNode syntax,
DiagnosticBag diagnostics)
{
string name;
ImmutableArray<MethodSymbol> explicitInterfaceImplementations;
GetNameAndExplicitInterfaceImplementations(
explicitlyImplementedPropertyOpt: null,
propertyName,
property.IsCompilationOutputWinMdObj(),
aliasQualifierOpt: null,
isGetMethod,
out name,
out explicitInterfaceImplementations);
var methodKind = isGetMethod ? MethodKind.PropertyGet : MethodKind.PropertySet;
return new SourcePropertyAccessorSymbol(
containingType,
name,
property,
propertyModifiers,
explicitInterfaceImplementations,
location,
syntax,
hasBody: false,
hasExpressionBody: false,
isIterator: false,
modifiers: new SyntaxTokenList(),
methodKind,
usesInit,
isAutoPropertyAccessor: true,
isExplicitInterfaceImplementation: false,
diagnostics);
}
#nullable restore
internal override bool IsExpressionBodied
=> _isExpressionBodied;
......@@ -197,39 +250,43 @@ internal sealed override ImmutableArray<string> NotNullWhenFalseMembers
}
}
#nullable enable
private SourcePropertyAccessorSymbol(
NamedTypeSymbol containingType,
string name,
SourcePropertySymbol property,
SourcePropertySymbolBase property,
DeclarationModifiers propertyModifiers,
ImmutableArray<MethodSymbol> explicitInterfaceImplementations,
Location location,
AccessorDeclarationSyntax syntax,
CSharpSyntaxNode syntax,
bool hasBody,
bool hasExpressionBody,
bool isIterator,
SyntaxTokenList modifiers,
MethodKind methodKind,
bool usesInit,
bool isAutoPropertyAccessor,
bool isExplicitInterfaceImplementation,
DiagnosticBag diagnostics)
: base(containingType,
syntax.GetReference(),
location,
isIterator: SyntaxFacts.HasYieldOperations(syntax.Body))
isIterator: isIterator)
{
_property = property;
_explicitInterfaceImplementations = explicitInterfaceImplementations;
_name = name;
_isAutoPropertyAccessor = isAutoPropertyAccessor;
Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties");
var hasBody = syntax.Body != null;
var hasExpressionBody = syntax.ExpressionBody != null;
_isExpressionBodied = !hasBody && hasExpressionBody;
_usesInit = syntax.Keyword.IsKind(SyntaxKind.InitKeyword);
_usesInit = usesInit;
if (_usesInit)
{
Binder.CheckFeatureAvailability(syntax, MessageID.IDS_FeatureInitOnlySetters, diagnostics, syntax.Keyword.GetLocation());
Binder.CheckFeatureAvailability(syntax, MessageID.IDS_FeatureInitOnlySetters, diagnostics, location);
}
bool modifierErrors;
var declarationModifiers = this.MakeModifiers(syntax, isExplicitInterfaceImplementation, hasBody || hasExpressionBody, location, diagnostics, out modifierErrors);
var declarationModifiers = this.MakeModifiers(modifiers, isExplicitInterfaceImplementation, hasBody || hasExpressionBody, location, diagnostics, out modifierErrors);
// Include some modifiers from the containing property, but not the accessibility modifiers.
declarationModifiers |= GetAccessorModifiers(propertyModifiers) & ~DeclarationModifiers.AccessibilityMask;
......@@ -274,9 +331,8 @@ internal sealed override ImmutableArray<string> NotNullWhenFalseMembers
}
}
CheckForBlockAndExpressionBody(
syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
}
#nullable restore
private static DeclarationModifiers GetAccessorModifiers(DeclarationModifiers propertyModifiers) =>
propertyModifiers & ~(DeclarationModifiers.Indexer | DeclarationModifiers.ReadOnly);
......@@ -525,7 +581,7 @@ internal override bool IsDeclaredReadOnly
internal override bool IsInitOnly => !IsStatic && _usesInit;
private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, bool isExplicitInterfaceImplementation,
private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, bool isExplicitInterfaceImplementation,
bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
{
// No default accessibility. If unset, accessibility
......@@ -546,7 +602,7 @@ internal override bool IsDeclaredReadOnly
defaultInterfaceImplementationModifiers = DeclarationModifiers.AccessibilityMask;
}
var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);
var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);
ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods,
defaultInterfaceImplementationModifiers,
......@@ -610,7 +666,8 @@ internal static string GetAccessorName(string propertyName, bool getNotSet, bool
}
/// <returns>
/// <see cref="AccessorDeclarationSyntax"/> or <see cref="ArrowExpressionClauseSyntax"/>
/// The declaring syntax for the accessor, or property if there is no accessor-specific
/// syntax.
/// </returns>
internal CSharpSyntaxNode GetSyntax()
{
......@@ -661,8 +718,17 @@ public override bool IsImplicitlyDeclared
get
{
// Per design meeting resolution [see bug 11253], no source accessor is implicitly declared in C#,
// because there is "get", "set", or expression-body syntax.
// if there is "get", "set", or expression-body syntax.
switch (GetSyntax().Kind())
{
case SyntaxKind.GetAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
case SyntaxKind.InitAccessorDeclaration:
case SyntaxKind.ArrowExpressionClause:
return false;
};
return true;
}
}
......
......@@ -7,338 +7,144 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection;
using Microsoft.Cci;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SynthesizedRecordPropertySymbol : SourceOrRecordPropertySymbol
internal sealed class SynthesizedRecordPropertySymbol : SourcePropertySymbolBase, IAttributeTargetSymbol
{
private readonly ParameterSymbol _backingParameter;
internal override SynthesizedBackingFieldSymbol BackingField { get; }
public override MethodSymbol GetMethod { get; }
public override MethodSymbol SetMethod { get; }
public override NamedTypeSymbol ContainingType { get; }
public ParameterSymbol BackingParameter { get; }
public SynthesizedRecordPropertySymbol(
NamedTypeSymbol containingType,
SourceMemberContainerTypeSymbol containingType,
ParameterSymbol backingParameter,
DiagnosticBag diagnostics)
: base(backingParameter.Locations[0])
: base(containingType,
binder: null,
backingParameter.GetNonNullSyntaxNode(),
RefKind.None,
backingParameter.Name,
backingParameter.Locations[0],
diagnostics)
{
ContainingType = containingType;
_backingParameter = backingParameter;
string name = backingParameter.Name;
BackingField = new SynthesizedBackingFieldSymbol(
this,
GeneratedNames.MakeBackingFieldName(name),
isReadOnly: true,
isStatic: false,
hasInitializer: true);
GetMethod = new GetAccessorSymbol(this, name);
SetMethod = new InitAccessorSymbol(this, name, diagnostics);
BackingParameter = backingParameter;
}
public ParameterSymbol BackingParameter => _backingParameter;
internal override bool IsAutoProperty => true;
public override RefKind RefKind => RefKind.None;
public override TypeWithAnnotations TypeWithAnnotations => _backingParameter.TypeWithAnnotations;
public override ImmutableArray<CustomModifier> RefCustomModifiers => ImmutableArray<CustomModifier>.Empty;
public override ImmutableArray<ParameterSymbol> Parameters => ImmutableArray<ParameterSymbol>.Empty;
public override bool IsIndexer => false;
public override ImmutableArray<PropertySymbol> ExplicitInterfaceImplementations => ImmutableArray<PropertySymbol>.Empty;
public override Symbol ContainingSymbol => ContainingType;
public override ImmutableArray<Location> Locations => _backingParameter.Locations;
public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences => _backingParameter.DeclaringSyntaxReferences;
public override Accessibility DeclaredAccessibility => Accessibility.Public;
public override bool IsStatic => false;
public override bool IsVirtual => false;
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => this;
public override bool IsOverride => false;
AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AttributeLocation.None;
public override bool IsAbstract => false;
AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.None;
public override bool IsSealed => false;
protected override Location TypeLocation
=> ((ParameterSyntax)CSharpSyntaxNode).Type!.Location;
public override bool IsExtern => false;
protected override SyntaxTokenList GetModifierTokens(SyntaxNode syntax)
=> new SyntaxTokenList();
internal override bool HasSpecialName => false;
protected override ArrowExpressionClauseSyntax? GetArrowExpression(SyntaxNode syntax)
=> null;
internal override CallingConvention CallingConvention => CallingConvention.HasThis;
protected override bool HasInitializer(SyntaxNode syntax)
=> true; // Synthesized record properties always have a synthesized initializer
internal override bool MustCallMethodsDirectly => false;
public override SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList
=> new SyntaxList<AttributeListSyntax>();
internal override ObsoleteAttributeData? ObsoleteAttributeData => null;
public override string Name => _backingParameter.Name;
protected override IAttributeTargetSymbol AttributesOwner => this;
protected override AttributeLocation AllowedAttributeLocations => AttributeLocation.None;
protected override AttributeLocation DefaultAttributeLocation => AttributeLocation.None;
public override ImmutableArray<CSharpAttributeData> GetAttributes() => ImmutableArray<CSharpAttributeData>.Empty;
internal override bool HasPointerType => Type.IsPointerType();
public override SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList => new SyntaxList<AttributeListSyntax>();
private sealed class GetAccessorSymbol : SynthesizedInstanceMethodSymbol
protected override void GetAccessorDeclarations(
CSharpSyntaxNode syntax,
DiagnosticBag diagnostics,
out bool isAutoProperty,
out bool hasAccessorList,
out bool accessorsHaveImplementation,
out bool isInitOnly,
out CSharpSyntaxNode? getSyntax,
out CSharpSyntaxNode? setSyntax)
{
private readonly SynthesizedRecordPropertySymbol _property;
public override string Name { get; }
isAutoProperty = true;
hasAccessorList = false;
getSyntax = setSyntax = syntax;
isInitOnly = true;
accessorsHaveImplementation = false;
}
public GetAccessorSymbol(SynthesizedRecordPropertySymbol property, string paramName)
protected override void CheckForBlockAndExpressionBody(CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
_property = property;
Name = SourcePropertyAccessorSymbol.GetAccessorName(
paramName,
getNotSet: true,
isWinMdOutput: false /* unused for getters */);
// Nothing to do here
}
public override MethodKind MethodKind => MethodKind.PropertyGet;
public override int Arity => 0;
public override bool IsExtensionMethod => false;
public override bool HidesBaseMethodsByName => false;
public override bool IsVararg => false;
public override bool ReturnsVoid => false;
public override bool IsAsync => false;
public override RefKind RefKind => RefKind.None;
public override TypeWithAnnotations ReturnTypeWithAnnotations => _property.TypeWithAnnotations;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations => ImmutableArray<TypeWithAnnotations>.Empty;
public override ImmutableArray<TypeParameterSymbol> TypeParameters => ImmutableArray<TypeParameterSymbol>.Empty;
public override ImmutableArray<ParameterSymbol> Parameters => _property.Parameters;
public override ImmutableArray<MethodSymbol> ExplicitInterfaceImplementations => ImmutableArray<MethodSymbol>.Empty;
public override ImmutableArray<CustomModifier> RefCustomModifiers => _property.RefCustomModifiers;
public override Symbol AssociatedSymbol => _property;
public override Symbol ContainingSymbol => _property.ContainingSymbol;
public override ImmutableArray<Location> Locations => _property.Locations;
public override Accessibility DeclaredAccessibility => _property.DeclaredAccessibility;
public override bool IsStatic => _property.IsStatic;
public override bool IsVirtual => _property.IsVirtual;
public override bool IsOverride => _property.IsOverride;
public override bool IsAbstract => _property.IsAbstract;
public override bool IsSealed => _property.IsSealed;
public override bool IsExtern => _property.IsExtern;
public override ImmutableHashSet<string> ReturnNotNullIfParameterNotNull => ImmutableHashSet<string>.Empty;
internal override bool HasSpecialName => _property.HasSpecialName;
internal override MethodImplAttributes ImplementationAttributes => MethodImplAttributes.Managed;
internal override bool HasDeclarativeSecurity => false;
internal override MarshalPseudoCustomAttributeData? ReturnValueMarshallingInformation => null;
internal override bool RequiresSecurityObject => false;
internal override CallingConvention CallingConvention => CallingConvention.HasThis;
internal override bool GenerateDebugInfo => false;
public override DllImportData? GetDllImportData() => null;
internal override ImmutableArray<string> GetAppliedConditionalSymbols()
=> ImmutableArray<string>.Empty;
internal override IEnumerable<SecurityAttribute> GetSecurityInformation()
=> Array.Empty<SecurityAttribute>();
internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) => false;
internal override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) => false;
internal override bool SynthesizesLoweredBoundBody => true;
internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
protected override DeclarationModifiers MakeModifiers(
SyntaxTokenList modifiers,
bool isExplicitInterfaceImplementation,
bool isIndexer,
bool accessorsHaveImplementation,
Location location,
DiagnosticBag diagnostics,
out bool modifierErrors)
{
// Method body:
//
// {
// return this.<>backingField;
// }
var F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics);
Debug.Assert(!isExplicitInterfaceImplementation);
Debug.Assert(!isIndexer);
modifierErrors = false;
F.CurrentFunction = this;
F.CloseMethod(F.Block(F.Return(F.Field(F.This(), _property.BackingField))));
}
return DeclarationModifiers.Public;
}
private sealed class InitAccessorSymbol : SynthesizedInstanceMethodSymbol
protected override SourcePropertyAccessorSymbol CreateAccessorSymbol(
bool isGet,
CSharpSyntaxNode? syntax,
PropertySymbol? explicitlyImplementedPropertyOpt,
string aliasQualifierOpt,
bool isAutoPropertyAccessor,
bool isExplicitInterfaceImplementation,
DiagnosticBag diagnostics)
{
private readonly SynthesizedRecordPropertySymbol _property;
public override TypeWithAnnotations ReturnTypeWithAnnotations { get; }
public override string Name { get; }
Debug.Assert(syntax is object);
Debug.Assert(isAutoPropertyAccessor);
return SourcePropertyAccessorSymbol.CreateAccessorSymbol(
isGet,
usesInit: !isGet, // the setter is always init-only
ContainingType,
this,
_modifiers,
_sourceName,
((ParameterSyntax)syntax).Identifier.GetLocation(),
syntax,
diagnostics);
}
public InitAccessorSymbol(
SynthesizedRecordPropertySymbol property,
string paramName,
protected override SourcePropertyAccessorSymbol CreateExpressionBodiedAccessor(
ArrowExpressionClauseSyntax syntax,
PropertySymbol? explicitlyImplementedPropertyOpt,
string aliasQualifierOpt,
bool isExplicitInterfaceImplementation,
DiagnosticBag diagnostics)
{
_property = property;
Name = SourcePropertyAccessorSymbol.GetAccessorName(
paramName,
getNotSet: false,
// https://github.com/dotnet/roslyn/issues/44684
isWinMdOutput: false);
var comp = property.DeclaringCompilation;
var type = TypeWithAnnotations.Create(comp.GetSpecialType(SpecialType.System_Void));
var initOnlyType = Binder.GetWellKnownType(
comp,
WellKnownType.System_Runtime_CompilerServices_IsExternalInit,
diagnostics,
property.Location);
var modifiers = ImmutableArray.Create<CustomModifier>(CSharpCustomModifier.CreateRequired(initOnlyType));
ReturnTypeWithAnnotations = type.WithModifiers(modifiers);
// There should be no expression-bodied synthesized record properties
throw ExceptionUtilities.Unreachable;
}
internal override bool IsInitOnly => true;
public override MethodKind MethodKind => MethodKind.PropertySet;
public override int Arity => 0;
public override bool IsExtensionMethod => false;
public override bool HidesBaseMethodsByName => false;
public override bool IsVararg => false;
public override bool ReturnsVoid => true;
public override bool IsAsync => false;
public override RefKind RefKind => RefKind.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations => ImmutableArray<TypeWithAnnotations>.Empty;
public override ImmutableArray<TypeParameterSymbol> TypeParameters => ImmutableArray<TypeParameterSymbol>.Empty;
public override ImmutableArray<ParameterSymbol> Parameters => ImmutableArray.Create(SynthesizedParameterSymbol.Create(
this,
_property.TypeWithAnnotations,
ordinal: 0,
RefKind.None,
name: ParameterSymbol.ValueParameterName));
public override ImmutableArray<MethodSymbol> ExplicitInterfaceImplementations => ImmutableArray<MethodSymbol>.Empty;
public override ImmutableArray<CustomModifier> RefCustomModifiers => _property.RefCustomModifiers;
public override Symbol AssociatedSymbol => _property;
public override Symbol ContainingSymbol => _property.ContainingSymbol;
public override ImmutableArray<Location> Locations => _property.Locations;
public override Accessibility DeclaredAccessibility => _property.DeclaredAccessibility;
public override bool IsStatic => _property.IsStatic;
public override bool IsVirtual => _property.IsVirtual;
public override bool IsOverride => _property.IsOverride;
public override bool IsAbstract => _property.IsAbstract;
public override bool IsSealed => _property.IsSealed;
public override bool IsExtern => _property.IsExtern;
public override ImmutableHashSet<string> ReturnNotNullIfParameterNotNull => ImmutableHashSet<string>.Empty;
internal override bool HasSpecialName => _property.HasSpecialName;
internal override MethodImplAttributes ImplementationAttributes => MethodImplAttributes.Managed;
internal override bool HasDeclarativeSecurity => false;
internal override MarshalPseudoCustomAttributeData? ReturnValueMarshallingInformation => null;
internal override bool RequiresSecurityObject => false;
internal override CallingConvention CallingConvention => CallingConvention.HasThis;
internal override bool GenerateDebugInfo => false;
public override DllImportData? GetDllImportData() => null;
internal override ImmutableArray<string> GetAppliedConditionalSymbols()
=> ImmutableArray<string>.Empty;
internal override IEnumerable<SecurityAttribute> GetSecurityInformation()
=> Array.Empty<SecurityAttribute>();
internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) => false;
internal override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) => false;
internal override bool SynthesizesLoweredBoundBody => true;
protected override ImmutableArray<ParameterSymbol> ComputeParameters(Binder? binder, CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
return ImmutableArray<ParameterSymbol>.Empty;
}
internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
protected override TypeWithAnnotations ComputeType(Binder? binder, SyntaxNode syntax, DiagnosticBag diagnostics)
{
// Method body:
//
// {
// this.<>backingField = value;
// }
return BackingParameter.TypeWithAnnotations;
}
var F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics);
protected override bool HasPointerTypeSyntactically
// Since we already bound the type, don't bother looking at syntax
=> TypeWithAnnotations.DefaultType.IsPointerOrFunctionPointer();
F.CurrentFunction = this;
F.CloseMethod(F.Block(
F.Assignment(F.Field(F.This(), _property.BackingField), F.Parameter(Parameters[0])),
F.Return()));
}
}
protected override ExplicitInterfaceSpecifierSyntax? GetExplicitInterfaceSpecifier(SyntaxNode syntax)
=> null;
protected override BaseParameterListSyntax? GetParameterListSyntax(CSharpSyntaxNode syntax)
=> null;
}
}
......@@ -32,7 +32,7 @@ internal override FlowAnalysisAnnotations FlowAnalysisAnnotations
get
{
var result = FlowAnalysisAnnotations.None;
if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbol property)
if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbolBase property)
{
if (property.HasDisallowNull)
{
......@@ -78,7 +78,7 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
{
base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbol property)
if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbolBase property)
{
var annotations = FlowAnalysisAnnotations;
if ((annotations & FlowAnalysisAnnotations.DisallowNull) != 0)
......
......@@ -16,13 +16,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
/// </summary>
internal sealed class SynthesizedBackingFieldSymbol : FieldSymbolWithAttributesAndModifiers
{
private readonly SourceOrRecordPropertySymbol _property;
private readonly SourcePropertySymbolBase _property;
private readonly string _name;
internal bool HasInitializer { get; }
protected override DeclarationModifiers Modifiers { get; }
public SynthesizedBackingFieldSymbol(
SourceOrRecordPropertySymbol property,
SourcePropertySymbolBase property,
string name,
bool isReadOnly,
bool isStatic,
......
......@@ -10232,5 +10232,22 @@ public static void Main()
303
");
}
[Fact]
public void SynthesizedRecordPointerProperty()
{
var src = @"
record R(int P1, int* P2, delegate*<int> P3);";
var comp = CreateCompilation(src);
var p = comp.GlobalNamespace.GetTypeMember("R").GetMember<SourcePropertySymbolBase>("P1");
Assert.False(p.HasPointerType);
p = comp.GlobalNamespace.GetTypeMember("R").GetMember<SourcePropertySymbolBase>("P2");
Assert.True(p.HasPointerType);
p = comp.GlobalNamespace.GetTypeMember("R").GetMember<SourcePropertySymbolBase>("P3");
Assert.True(p.HasPointerType);
}
}
}
......@@ -146,12 +146,13 @@ public void GeneratedProperties()
comp.VerifyDiagnostics();
var c = comp.GlobalNamespace.GetTypeMember("C");
var x = (SourceOrRecordPropertySymbol)c.GetProperty("x");
var x = (SourcePropertySymbolBase)c.GetProperty("x");
Assert.NotNull(x.GetMethod);
Assert.Equal(MethodKind.PropertyGet, x.GetMethod.MethodKind);
Assert.Equal(SpecialType.System_Int32, x.Type.SpecialType);
Assert.False(x.IsReadOnly);
Assert.False(x.IsWriteOnly);
Assert.False(x.IsImplicitlyDeclared);
Assert.Equal(Accessibility.Public, x.DeclaredAccessibility);
Assert.False(x.IsVirtual);
Assert.False(x.IsStatic);
......@@ -162,26 +163,30 @@ public void GeneratedProperties()
Assert.Equal(x, backing.AssociatedSymbol);
Assert.Equal(c, backing.ContainingSymbol);
Assert.Equal(c, backing.ContainingType);
Assert.True(backing.IsImplicitlyDeclared);
var getAccessor = x.GetMethod;
Assert.Equal(x, getAccessor.AssociatedSymbol);
Assert.True(getAccessor.IsImplicitlyDeclared);
Assert.Equal(c, getAccessor.ContainingSymbol);
Assert.Equal(c, getAccessor.ContainingType);
Assert.Equal(Accessibility.Public, getAccessor.DeclaredAccessibility);
var setAccessor = x.SetMethod;
Assert.Equal(x, setAccessor.AssociatedSymbol);
Assert.True(setAccessor.IsImplicitlyDeclared);
Assert.Equal(c, setAccessor.ContainingSymbol);
Assert.Equal(c, setAccessor.ContainingType);
Assert.Equal(Accessibility.Public, setAccessor.DeclaredAccessibility);
Assert.True(setAccessor.IsInitOnly);
var y = (SourceOrRecordPropertySymbol)c.GetProperty("y");
var y = (SourcePropertySymbolBase)c.GetProperty("y");
Assert.NotNull(y.GetMethod);
Assert.Equal(MethodKind.PropertyGet, y.GetMethod.MethodKind);
Assert.Equal(SpecialType.System_Int32, y.Type.SpecialType);
Assert.False(y.IsReadOnly);
Assert.False(y.IsWriteOnly);
Assert.False(y.IsImplicitlyDeclared);
Assert.Equal(Accessibility.Public, y.DeclaredAccessibility);
Assert.False(x.IsVirtual);
Assert.False(x.IsStatic);
......@@ -192,14 +197,17 @@ public void GeneratedProperties()
Assert.Equal(y, backing.AssociatedSymbol);
Assert.Equal(c, backing.ContainingSymbol);
Assert.Equal(c, backing.ContainingType);
Assert.True(backing.IsImplicitlyDeclared);
getAccessor = y.GetMethod;
Assert.Equal(y, getAccessor.AssociatedSymbol);
Assert.True(getAccessor.IsImplicitlyDeclared);
Assert.Equal(c, getAccessor.ContainingSymbol);
Assert.Equal(c, getAccessor.ContainingType);
setAccessor = y.SetMethod;
Assert.Equal(y, setAccessor.AssociatedSymbol);
Assert.True(setAccessor.IsImplicitlyDeclared);
Assert.Equal(c, setAccessor.ContainingSymbol);
Assert.Equal(c, setAccessor.ContainingType);
Assert.Equal(Accessibility.Public, setAccessor.DeclaredAccessibility);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册