Skip to content

Conversation

@jcouv
Copy link
Member

@jcouv jcouv commented Sep 24, 2025

Addresses part of #78963 ("Add Name property to synthesized attribute")
This shape matches that of the BCL attribute: dotnet/runtime#118179

Relates to test plan #76130

@jcouv jcouv self-assigned this Sep 24, 2025
@jcouv jcouv added Area-Compilers Feature - Extension Everything The extension everything feature labels Sep 24, 2025
@jcouv jcouv mentioned this pull request Sep 24, 2025
28 tasks
@jcouv jcouv marked this pull request as ready for review September 25, 2025 04:10
@jcouv jcouv requested a review from a team as a code owner September 25, 2025 04:10
}

public override IEnumerable<string> MemberNames
=> [_nameField.Name, PropertyName, WellKnownMemberNames.InstanceConstructorName];
Copy link
Member

@jjonescz jjonescz Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using only constants:

Suggested change
=> [_nameField.Name, PropertyName, WellKnownMemberNames.InstanceConstructorName];
=> [FieldName, PropertyName, WellKnownMemberNames.InstanceConstructorName];
``` #Resolved

public override MethodSymbol GetMethod { get; }
public override MethodSymbol? SetMethod => null;
public override Symbol ContainingSymbol => _backingField.ContainingSymbol;
public override Accessibility DeclaredAccessibility => Accessibility.Internal;
Copy link
Member

@jjonescz jjonescz Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be public to match the runtime API? #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The embedded type is internal (see SynthesizedEmbeddedAttributeSymbolBase.DeclaredAccessibility), so public or internal here are equivalent

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should match the accesibility

public override ImmutableArray<ParameterSymbol> Parameters => [];
public override ImmutableArray<MethodSymbol> ExplicitInterfaceImplementations => [];
public override ImmutableArray<Location> Locations => [];
public override Accessibility DeclaredAccessibility => Accessibility.Internal;
Copy link
Member

@jjonescz jjonescz Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have the same accessibility as the property?

Suggested change
public override Accessibility DeclaredAccessibility => Accessibility.Internal;
public override Accessibility DeclaredAccessibility => AssociatedSymbol.DeclaredAccessibility;
``` #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the same and we already know the value, so doesn't seem useful to delegate

m => ImmutableArray.Create(SynthesizedParameterSymbol.Create(m, TypeWithAnnotations.Create(systemStringType), 0, RefKind.None, name: "name"))));
Debug.Assert(FieldName == GeneratedNames.MakeBackingFieldName(PropertyName));

_nameField = new SynthesizedFieldSymbol(this, systemStringType, FieldName);
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SynthesizedFieldSymbol

isReadOnly: true? #Closed

private sealed class ConstructorSymbol : SynthesizedInstanceConstructor
{
private readonly ImmutableArray<ParameterSymbol> _parameters;
private readonly SynthesizedFieldSymbol _nameField;
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private readonly SynthesizedFieldSymbol _nameField;

I think this storage is redundant because the field symbol is available from containing type (through a private field) #Closed

SynthesizedFieldSymbol nameField) :
base(containingType)
{
_parameters = [SynthesizedParameterSymbol.Create(containingType, TypeWithAnnotations.Create(systemStringType), ordinal: 0, RefKind.None, name: "name")];
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

containingType

The container for parameter looks wrong #Closed

public override IEnumerable<string> MemberNames
=> [FieldName, PropertyName, WellKnownMemberNames.InstanceConstructorName];

private sealed class ConstructorSymbol : SynthesizedInstanceConstructor
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConstructorSymbol

Would it make sense to use existing SynthesizedEmbeddedAttributeConstructorWithBodySymbol instead defining new class? #Closed

private sealed partial class NameGetAccessorMethodSymbol : SynthesizedMethodSymbol
{
private readonly NamePropertySymbol _nameProperty;
private readonly SynthesizedFieldSymbol _backingField;
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private readonly SynthesizedFieldSymbol _backingField;

This field looks redundant #Closed


internal override void GenerateMethodBody(TypeCompilationState compilationState, BindingDiagnosticBag diagnostics)
{
SyntheticBoundNodeFactory F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics);
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.GetNonNullSyntaxNode()

Is there a chance that is is going to produce non-Dummy node? If not, consider using it directly. #Closed

public override ImmutableArray<ParameterSymbol> Parameters => [];
public override ImmutableArray<MethodSymbol> ExplicitInterfaceImplementations => [];
public override ImmutableArray<Location> Locations => [];
public override Accessibility DeclaredAccessibility => Accessibility.Internal;
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility.Internal

I think accessibility should be public #Closed

Copy link
Member Author

@jcouv jcouv Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? Forget it, it's fine

}
catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
{
diagnostics.Add(ex.Diagnostic);
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diagnostics.Add(ex.Diagnostic);

It looks like other similar places also do F.CloseMethod(F.ThrowNull()); #Closed

IL_000d: ret
} // end of method ExtensionMarkerAttribute::.ctor
// Properties
.property instance string Name()
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.property instance string Name()

Is there a way to test runtime behavior of this property. Perhaps getting it from an applied attribute through a reflection? #Closed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a test below does that.

{
FieldName => [_nameField],
PropertyName => [_nameProperty],
WellKnownMemberNames.InstanceConstructorName => [_constructors[0]],
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[_constructors[0]]

_constructors? #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types don't line up

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types don't line up

There is a CastUp helper that allows to cast to an array of base class without reallocation

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Sep 25, 2025

Done with review pass (commit 2) #Closed

try
{
// return this._backingField;
F.CloseMethod(F.Return(F.Field(F.This(), ((SynthesizedEmbeddedExtensionMarkerAttributeSymbol)_nameProperty.ContainingSymbol)._nameField)));
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

((SynthesizedEmbeddedExtensionMarkerAttributeSymbol)_nameProperty.ContainingSymbol)._nameField

It looks like this is a "longer" way to get to _nameProperty._backingField, which is going to read that field in order to calculate _nameProperty.ContainingSymbol. #Closed

// Fields
.field private initonly string '<Name>k__BackingField'
// Methods
.method assembly hidebysig specialname
Copy link
Contributor

@AlekseyTs AlekseyTs Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assembly

I would expect accessibility changed to public #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Sep 25, 2025

Done with review pass (commit 3) #Closed

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 5)

@jcouv jcouv merged commit e477ee2 into dotnet:main Sep 26, 2025
24 checks passed
@jcouv jcouv deleted the extensions-name branch September 26, 2025 16:21
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Sep 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Feature - Extension Everything The extension everything feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants