未验证 提交 ba014d9d 编写于 作者: A AlekseyTs 提交者: GitHub

Support applying attributes to properties and fields that are created to back...

Support applying attributes to properties and fields that are created to back primary constructor parameters in records. (#45908)

Closes #44691.
上级 7023b0bb
......@@ -129,9 +129,22 @@ private static OverriddenOrHiddenMembersResult MakeOverriddenOrHiddenMembersWork
return MakeInterfaceOverriddenOrHiddenMembers(member, memberIsFromSomeCompilation);
}
Symbol bestMatch = null;
ArrayBuilder<Symbol> hiddenBuilder = null;
ArrayBuilder<Symbol> hiddenBuilder;
ImmutableArray<Symbol> overriddenMembers;
ImmutableArray<Symbol> runtimeOverriddenMembers;
FindOverriddenOrHiddenMembers(member, containingType, memberIsFromSomeCompilation, out hiddenBuilder, out overriddenMembers, out runtimeOverriddenMembers);
ImmutableArray<Symbol> hiddenMembers = hiddenBuilder == null ? ImmutableArray<Symbol>.Empty : hiddenBuilder.ToImmutableAndFree();
return OverriddenOrHiddenMembersResult.Create(overriddenMembers, hiddenMembers, runtimeOverriddenMembers);
}
private static void FindOverriddenOrHiddenMembers(Symbol member, NamedTypeSymbol containingType, bool memberIsFromSomeCompilation,
out ArrayBuilder<Symbol> hiddenBuilder,
out ImmutableArray<Symbol> overriddenMembers,
out ImmutableArray<Symbol> runtimeOverriddenMembers)
{
Symbol bestMatch = null;
hiddenBuilder = null;
for (NamedTypeSymbol currType = containingType.BaseTypeNoUseSiteDiagnostics;
(object)currType != null && (object)bestMatch == null && hiddenBuilder == null;
currType = currType.BaseTypeNoUseSiteDiagnostics)
......@@ -149,12 +162,19 @@ private static OverriddenOrHiddenMembersResult MakeOverriddenOrHiddenMembersWork
// Based on bestMatch, find other methods that will be overridden, hidden, or runtime overridden
// (in bestMatch.ContainingType).
ImmutableArray<Symbol> overriddenMembers;
ImmutableArray<Symbol> runtimeOverriddenMembers;
FindRelatedMembers(member.IsOverride, memberIsFromSomeCompilation, member.Kind, bestMatch, out overriddenMembers, out runtimeOverriddenMembers, ref hiddenBuilder);
}
ImmutableArray<Symbol> hiddenMembers = hiddenBuilder == null ? ImmutableArray<Symbol>.Empty : hiddenBuilder.ToImmutableAndFree();
return OverriddenOrHiddenMembersResult.Create(overriddenMembers, hiddenMembers, runtimeOverriddenMembers);
public static Symbol FindFirstHiddenMemberIfAny(Symbol member, bool memberIsFromSomeCompilation)
{
ArrayBuilder<Symbol> hiddenBuilder;
FindOverriddenOrHiddenMembers(member, member.ContainingType, memberIsFromSomeCompilation, out hiddenBuilder,
overriddenMembers: out _, runtimeOverriddenMembers: out _);
Symbol result = hiddenBuilder?.FirstOrDefault();
hiddenBuilder?.Free();
return result;
}
/// <summary>
......
......@@ -75,7 +75,7 @@ internal sealed class SignatureOnlyPropertySymbol : PropertySymbol
public override bool IsVirtual { get { throw ExceptionUtilities.Unreachable; } }
public override bool IsOverride { get { throw ExceptionUtilities.Unreachable; } }
public override bool IsOverride => false;
public override bool IsAbstract { get { throw ExceptionUtilities.Unreachable; } }
......
......@@ -341,7 +341,18 @@ public override string MetadataName
AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.Parameter;
AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AttributeLocation.Parameter;
AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations
{
get
{
if (SynthesizedRecordPropertySymbol.HaveCorrespondingSynthesizedRecordPropertySymbol(this))
{
return AttributeLocation.Parameter | AttributeLocation.Property | AttributeLocation.Field;
}
return AttributeLocation.Parameter;
}
}
/// <summary>
/// Symbol to copy bound attributes from, or null if the attributes are not shared among multiple source parameter symbols.
......
......@@ -3079,16 +3079,24 @@ ImmutableArray<PropertySymbol> addProperties(ImmutableArray<ParameterSymbol> rec
{
bool isInherited = false;
var syntax = param.GetNonNullSyntaxNode();
var property = new SynthesizedRecordPropertySymbol(this, syntax, param, isOverride: false, diagnostics);
if (!memberSignatures.TryGetValue(property, out var existingMember))
var targetProperty = new SignatureOnlyPropertySymbol(param.Name,
this,
ImmutableArray<ParameterSymbol>.Empty,
RefKind.None,
param.TypeWithAnnotations,
ImmutableArray<CustomModifier>.Empty,
isStatic: false,
ImmutableArray<PropertySymbol>.Empty);
if (!memberSignatures.TryGetValue(targetProperty, out var existingMember))
{
Debug.Assert(property.OverriddenOrHiddenMembers.OverriddenMembers.Length == 0); // property is not virtual and should not have overrides
existingMember = property.OverriddenOrHiddenMembers.HiddenMembers.FirstOrDefault();
existingMember = OverriddenOrHiddenMembersHelpers.FindFirstHiddenMemberIfAny(targetProperty, memberIsFromSomeCompilation: true);
isInherited = true;
}
if (existingMember is null)
{
addProperty(property);
addProperty(new SynthesizedRecordPropertySymbol(this, syntax, param, isOverride: false, diagnostics));
}
else if (existingMember is PropertySymbol { IsStatic: false, GetMethod: { } } prop
&& prop.TypeWithAnnotations.Equals(param.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions))
......
......@@ -139,6 +139,8 @@ private static bool HasInitializer(SyntaxNode syntax)
public override SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList
=> ((BasePropertyDeclarationSyntax)CSharpSyntaxNode).AttributeLists;
public override IAttributeTargetSymbol AttributesOwner => this;
private static void GetAccessorDeclarations(
CSharpSyntaxNode syntaxNode,
DiagnosticBag diagnostics,
......
......@@ -705,8 +705,6 @@ internal CSharpSyntaxNode CSharpSyntaxNode
}
}
public abstract SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList { get; }
internal SyntaxTree SyntaxTree
{
get
......@@ -980,7 +978,11 @@ private SynthesizedSealedPropertyAccessor MakeSynthesizedSealedAccessor()
#region Attributes
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => this;
public abstract SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList { get; }
public abstract IAttributeTargetSymbol AttributesOwner { get; }
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => AttributesOwner;
AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.Property;
......
......@@ -119,12 +119,12 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
{
var F = new SyntheticBoundNodeFactory(this, ContainingType.GetNonNullSyntaxNode(), compilationState, diagnostics);
var members = ContainingType.GetMembers(WellKnownMemberNames.InstanceConstructorName);
var members = ContainingType.InstanceConstructors;
foreach (var member in members)
{
var ctor = (MethodSymbol)member;
if (ctor.ParameterCount == 1 &&
ctor.Parameters[0].Type.Equals(ContainingType, TypeCompareKind.ConsiderEverything))
if (ctor.ParameterCount == 1 && ctor.Parameters[0].RefKind == RefKind.None &&
ctor.Parameters[0].Type.Equals(ContainingType, TypeCompareKind.AllIgnoreOptions))
{
F.CloseMethod(F.Return(F.New(ctor, F.This())));
return;
......
......@@ -15,7 +15,7 @@
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SynthesizedRecordEqualityContractProperty : SourcePropertySymbolBase, IAttributeTargetSymbol
internal sealed class SynthesizedRecordEqualityContractProperty : SourcePropertySymbolBase
{
internal const string PropertyName = "EqualityContract";
......@@ -52,11 +52,10 @@ internal sealed class SynthesizedRecordEqualityContractProperty : SourceProperty
public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences => ImmutableArray<SyntaxReference>.Empty;
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => this;
AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AttributeLocation.None;
public override SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList
=> new SyntaxList<AttributeListSyntax>();
AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.None;
public override IAttributeTargetSymbol AttributesOwner => this;
protected override Location TypeLocation
=> ContainingType.Locations[0];
......@@ -64,9 +63,6 @@ protected override Location TypeLocation
protected override SyntaxTokenList GetModifierTokens(SyntaxNode syntax)
=> new SyntaxTokenList();
public override SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList
=> new SyntaxList<AttributeListSyntax>();
protected override void CheckForBlockAndExpressionBody(CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
// Nothing to do here
......
......@@ -11,9 +11,9 @@
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SynthesizedRecordPropertySymbol : SourcePropertySymbolBase, IAttributeTargetSymbol
internal sealed class SynthesizedRecordPropertySymbol : SourcePropertySymbolBase
{
public ParameterSymbol BackingParameter { get; }
public SourceParameterSymbol BackingParameter { get; }
public SynthesizedRecordPropertySymbol(
SourceMemberContainerTypeSymbol containingType,
......@@ -42,14 +42,11 @@ internal sealed class SynthesizedRecordPropertySymbol : SourcePropertySymbolBase
hasParameters: false,
diagnostics)
{
BackingParameter = backingParameter;
BackingParameter = (SourceParameterSymbol)backingParameter;
}
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => this;
AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AttributeLocation.None;
AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.None;
public override IAttributeTargetSymbol AttributesOwner => BackingParameter as IAttributeTargetSymbol ?? this;
protected override Location TypeLocation
=> ((ParameterSyntax)CSharpSyntaxNode).Type!.Location;
......@@ -58,7 +55,7 @@ protected override SyntaxTokenList GetModifierTokens(SyntaxNode syntax)
=> new SyntaxTokenList();
public override SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList
=> new SyntaxList<AttributeListSyntax>();
=> BackingParameter.AttributeDeclarationList;
protected override void CheckForBlockAndExpressionBody(CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
......@@ -112,5 +109,10 @@ protected override TypeWithAnnotations ComputeType(Binder? binder, SyntaxNode sy
protected override bool HasPointerTypeSyntactically
// Since we already bound the type, don't bother looking at syntax
=> TypeWithAnnotations.DefaultType.IsPointerOrFunctionPointer();
public static bool HaveCorrespondingSynthesizedRecordPropertySymbol(SourceParameterSymbol parameter)
{
return parameter.ContainingType.GetMembersUnordered().Any((s, parameter) => (s as SynthesizedRecordPropertySymbol)?.BackingParameter == (object)parameter, parameter);
}
}
}
......@@ -41,7 +41,7 @@ internal sealed class SynthesizedBackingFieldSymbol : FieldSymbolWithAttributesA
}
protected override IAttributeTargetSymbol AttributeOwner
=> _property;
=> _property.AttributesOwner;
internal override Location ErrorLocation
=> _property.Location;
......
......@@ -359,6 +359,22 @@ public static ImmutableArray<T> WhereAsArray<T>(this ImmutableArray<T> array, Fu
}
}
public static bool Any<T, TArg>(this ImmutableArray<T> array, Func<T, TArg, bool> predicate, TArg arg)
{
int n = array.Length;
for (int i = 0; i < n; i++)
{
var a = array[i];
if (predicate(a, arg))
{
return true;
}
}
return false;
}
/// <summary>
/// Casts the immutable array of a Type to an immutable array of its base type.
/// </summary>
......
......@@ -1506,6 +1506,11 @@ internal static IEnumerable<string> GetAttributeStrings(ImmutableArray<CSharpAtt
return attributes.Select(a => a.ToString());
}
internal static IEnumerable<string> GetAttributeStrings(IEnumerable<CSharpAttributeData> attributes)
{
return attributes.Select(a => a.ToString());
}
#endregion
#region Documentation Comments
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册