Skip to content

Commit 9b0d740

Browse files
author
Julien Couvreur
committed
Extensions: address follow-ups for new metadata design
1 parent 21dede8 commit 9b0d740

23 files changed

+2507
-808
lines changed

src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ private static void GetDocumentsForMethodsAndNestedTypes(PooledHashSet<Cci.Debug
382382
switch (member.Kind)
383383
{
384384
case SymbolKind.NamedType:
385-
if (!((NamedTypeSymbol)member).IsExtension) // PROTOTYPE: Figure out what to do about extensions, if anything
385+
if (!((NamedTypeSymbol)member).IsExtension) // Tracked by https://github.com/dotnet/roslyn/issues/78963 : Figure out what to do about extensions, if anything
386386
{
387387
namespacesAndTypesToProcess.Push((NamespaceOrTypeSymbol)member);
388388
}

src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ private void AddNameAndTypeArgumentsOrParameters(INamedTypeSymbol symbol)
345345
{
346346
if (Format.CompilerInternalOptions.HasFlag(SymbolDisplayCompilerInternalOptions.UseMetadataMemberNames))
347347
{
348-
// PROTOTYPE: What should we output as the name here
348+
// Tracked by https://github.com/dotnet/roslyn/issues/78957 : public API, should we output ExtensionMarkerName instead here?
349349
var extensionIdentifier = underlyingTypeSymbol!.ExtensionGroupingName; // Tracked by https://github.com/dotnet/roslyn/issues/78957 : public API, use public API once it's available
350350
Builder.Add(CreatePart(SymbolDisplayPartKind.ClassName, symbol, extensionIdentifier));
351351
}

src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,9 +1012,11 @@ public override ImmutableArray<CSharpAttributeData> GetAttributes()
10121012
bool checkForRequiredMembers = this.ShouldCheckRequiredMembers() && this.ContainingType.HasAnyRequiredMembers;
10131013
bool isInstanceIncrementDecrementOrCompoundAssignmentOperator = SourceMethodSymbol.IsInstanceIncrementDecrementOrCompoundAssignmentOperator(this);
10141014

1015+
bool isNewExtensionMember = this.GetIsNewExtensionMember();
1016+
10151017
bool isExtensionMethod = false;
10161018
bool isReadOnly = false;
1017-
if (checkForExtension || checkForIsReadOnly || checkForRequiredMembers || isInstanceIncrementDecrementOrCompoundAssignmentOperator)
1019+
if (checkForExtension || checkForIsReadOnly || checkForRequiredMembers || isInstanceIncrementDecrementOrCompoundAssignmentOperator || isNewExtensionMember)
10181020
{
10191021
attributeData = containingPEModuleSymbol.GetCustomAttributesForToken(_handle,
10201022
filteredOutAttribute1: out CustomAttributeHandle extensionAttribute,
@@ -1026,7 +1028,7 @@ public override ImmutableArray<CSharpAttributeData> GetAttributes()
10261028
filteredOutAttribute4: out _,
10271029
filterOut4: (checkForRequiredMembers && ObsoleteAttributeData is null) ? AttributeDescription.ObsoleteAttribute : default,
10281030
filteredOutAttribute5: out _,
1029-
filterOut5: default,
1031+
filterOut5: AttributeDescription.ExtensionMarkerNameAttribute,
10301032
filteredOutAttribute6: out _,
10311033
filterOut6: default);
10321034

@@ -1483,7 +1485,7 @@ internal override UseSiteInfo<AssemblySymbol> GetUseSiteInfo()
14831485

14841486
if (_containingType.IsExtension &&
14851487
(TryGetCorrespondingExtensionImplementationMethod() is null ||
1486-
_containingType.GetUseSiteInfo().DiagnosticInfo?.DefaultSeverity == DiagnosticSeverity.Error)) // PROTOTYPE: Cover mismatch in type parameters between grouping and marker method with a test (See usage of MatchesContainingTypeParameters helper).
1488+
_containingType.GetUseSiteInfo().DiagnosticInfo?.DefaultSeverity == DiagnosticSeverity.Error))
14871489
{
14881490
diagnosticInfo = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this);
14891491
}

src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,6 @@ public override ImmutableArray<CSharpAttributeData> GetAttributes()
936936
if (IsExtension)
937937
{
938938
// We do not recognize any attributes on extension blocks
939-
// PROTOTYPE: Add a test demonstrating the fact that we do not load attributes from grouping and marker types.
940939
loadedCustomAttributes = [];
941940
requiredHandle = default;
942941
}
@@ -1863,7 +1862,7 @@ public override string Name
18631862
{
18641863
get
18651864
{
1866-
return IsExtension ? "" : _name; // PROTOTYPE: add test coverage
1865+
return IsExtension ? "" : _name;
18671866
}
18681867
}
18691868

@@ -1874,7 +1873,7 @@ public override string MetadataName
18741873
if (IsExtension)
18751874
{
18761875
Debug.Assert(!MangleName);
1877-
return _name; // PROTOTYPE: add test coverage
1876+
return _name;
18781877
}
18791878

18801879
return base.MetadataName;
@@ -2165,7 +2164,6 @@ private IEnumerable<PENamedTypeSymbol> CreateNestedTypes()
21652164
if (IsExtension)
21662165
{
21672166
// We do not support type declarations in extension blocks
2168-
// PROTOTYPE: Add a test demonstrating the fact that we do not load nested types from grouping and marker types.
21692167
yield break;
21702168
}
21712169

@@ -2183,7 +2181,7 @@ private IEnumerable<PENamedTypeSymbol> CreateNestedTypes()
21832181
yield break;
21842182
}
21852183

2186-
// PROTOTYPE: test effect of every condition here
2184+
// Tracked by https://github.com/dotnet/roslyn/issues/78963 : test effect of every condition here
21872185
bool checkForExtensionGroup = this.IsStatic && this.ContainingType is null && this.TypeKind == TypeKind.Class &&
21882186
module.HasExtensionAttribute(_handle, ignoreCase: false) && !this.IsGenericType;
21892187

@@ -2203,7 +2201,7 @@ private IEnumerable<PENamedTypeSymbol> CreateNestedTypes()
22032201
{
22042202
var type = PENamedTypeSymbol.Create(moduleSymbol, this, typeRid);
22052203

2206-
// PROTOTYPE: test effect of every condition here
2204+
// Tracked by https://github.com/dotnet/roslyn/issues/78963 : test effect of every condition here
22072205
if (checkForExtensionGroup &&
22082206
type.DeclaredAccessibility == Accessibility.Public &&
22092207
type.HasSpecialName && type.IsSealed && module.HasExtensionAttribute(type.Handle, ignoreCase: false) &&
@@ -2226,7 +2224,7 @@ private IEnumerable<PENamedTypeSymbol> CreateNestedTypes()
22262224
{
22272225
var marker = PENamedTypeSymbol.Create(moduleSymbol, type, markerRid);
22282226

2229-
// PROTOTYPE: test effect of every condition here
2227+
// Tracked by https://github.com/dotnet/roslyn/issues/78963 : test effect of every condition here
22302228
if (marker.HasSpecialName && marker.IsStatic && marker.DeclaredAccessibility == Accessibility.Public &&
22312229
marker.TypeKind == TypeKind.Class && marker.BaseTypeNoUseSiteDiagnostics.IsObjectType() && marker.Arity == 0 &&
22322230
marker.InterfacesNoUseSiteDiagnostics().IsEmpty &&
@@ -2254,7 +2252,6 @@ private MultiDictionary<string, PEFieldSymbol> CreateFields(ArrayBuilder<PEField
22542252

22552253
if (IsExtension)
22562254
{
2257-
// PROTOTYPE: Add a test demonstrating the fact that we do not load fields from grouping and marker types.
22582255
return privateFieldNameToSymbols;
22592256
}
22602257

@@ -2352,16 +2349,13 @@ private PooledDictionary<MethodDefinitionHandle, PEMethodSymbol> CreateMethods(A
23522349
var isOrdinaryEmbeddableStruct = (this.TypeKind == TypeKind.Struct) && (this.SpecialType == Microsoft.CodeAnalysis.SpecialType.None) && this.ContainingAssembly.IsLinked;
23532350
bool isExtension = IsExtension;
23542351

2355-
// PROTOTYPE: Add a test demonstrating the fact that we do not load methods from marker types into the extension blocks.
2356-
23572352
try
23582353
{
23592354
foreach (var methodHandle in module.GetMethodsOfTypeOrThrow(isExtension ? _lazyUncommonProperties.extensionInfo.GroupingTypeSymbol.Handle : _handle))
23602355
{
23612356
if (isOrdinaryEmbeddableStruct || module.ShouldImportMethod(_handle, methodHandle, moduleSymbol.ImportOptions))
23622357
{
2363-
// PROTOTYPE: Would it be worth building a map across all methods to optimize this?
2364-
// PROTOTYPE: Should we strip the ExtensionMarkerNameAttribute from GetAttributes()?
2358+
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : optimization, would it be worth building a map across all methods to optimize this?
23652359
if (isExtension && (!module.HasExtensionMarkerNameAttribute(methodHandle, out string markerName) || markerName != MetadataName))
23662360
{
23672361
// Method doesn't belong to this extension block
@@ -2386,16 +2380,13 @@ private void CreateProperties(Dictionary<MethodDefinitionHandle, PEMethodSymbol>
23862380
var module = moduleSymbol.Module;
23872381
bool isExtension = IsExtension;
23882382

2389-
// PROTOTYPE: Add a test demonstrating the fact that we do not load properties from marker types into extension blocks.
2390-
23912383
try
23922384
{
23932385
foreach (var propertyDef in module.GetPropertiesOfTypeOrThrow(isExtension ? _lazyUncommonProperties.extensionInfo.GroupingTypeSymbol.Handle : _handle))
23942386
{
23952387
try
23962388
{
2397-
// PROTOTYPE: Would it be worth building a map across all properties to optimize this?
2398-
// PROTOTYPE: Should we strip the ExtensionMarkerNameAttribute from GetAttributes()?
2389+
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : optimization, would it be worth building a map across all properties to optimize this?
23992390
if (isExtension && (!module.HasExtensionMarkerNameAttribute(propertyDef, out string markerName) || markerName != MetadataName))
24002391
{
24012392
// Property doesn't belong to this extension block
@@ -2428,7 +2419,6 @@ private void CreateEvents(
24282419
if (IsExtension)
24292420
{
24302421
// We do not support event declarations in extension blocks
2431-
// PROTOTYPE: Add a test demonstrating the fact that we do not load events from grouping and marker types.
24322422
return;
24332423
}
24342424

@@ -2704,7 +2694,7 @@ internal override string ExtensionGroupingName
27042694
throw ExceptionUtilities.Unreachable();
27052695
}
27062696

2707-
return _lazyUncommonProperties.extensionInfo.GroupingTypeSymbol.MetadataName; // PROTOTYPE: is this the right value to return?
2697+
return _lazyUncommonProperties.extensionInfo.GroupingTypeSymbol.MetadataName;
27082698
}
27092699
}
27102700

@@ -3149,7 +3139,6 @@ protected override DiagnosticInfo GetUseSiteDiagnosticImpl()
31493139
}
31503140
else if (IsExtension && !((PENamedTypeSymbolGeneric)_lazyUncommonProperties.extensionInfo.MarkerTypeSymbol).MatchesContainingTypeParameters())
31513141
{
3152-
// PROTOTYPE: Cover this code path with a test.
31533142
diagnostic = new CSDiagnosticInfo(ErrorCode.ERR_BogusType, this);
31543143
}
31553144
}

src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,15 @@ public override ImmutableArray<CSharpAttributeData> GetAttributes()
738738
out _,
739739
this.RefKind == RefKind.RefReadOnly ? AttributeDescription.IsReadOnlyAttribute : default,
740740
out CustomAttributeHandle required,
741-
AttributeDescription.RequiredMemberAttribute);
741+
AttributeDescription.RequiredMemberAttribute,
742+
out _,
743+
this.GetIsNewExtensionMember() ? AttributeDescription.ExtensionMarkerNameAttribute : default,
744+
out _,
745+
default,
746+
out _,
747+
default,
748+
out _,
749+
default);
742750

743751
if (!attributes.IsEmpty)
744752
{

src/Compilers/CSharp/Portable/Symbols/Source/ExtensionGroupingInfo.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public Cci.TypeMemberVisibility GetCorrespondingMarkerMethodVisibility(Synthesiz
137137
}
138138
}
139139

140-
// PROTOTYPE: Is there a real need to cache this result for reuse?
140+
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : optimization, Is there a real need to cache this result for reuse?
141141
return result;
142142
}
143143

@@ -508,7 +508,6 @@ public override IEnumerable<ICustomAttribute> GetAttributes(EmitContext context)
508508
// Preserve only the synthesized IsUnmanagedAttribute.
509509
if (MustBeValueType)
510510
{
511-
// PROTOTYPE: Make sure we have coverage for the WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor case
512511
var unmanagedCtor = ((PEModuleBuilder)context.Module).TryGetSynthesizedIsUnmanagedAttribute()?.Constructors[0] ??
513512
((ExtensionGroupingType)DefiningType).ExtensionMarkerTypes[0].UnderlyingExtensions[0].DeclaringCompilation.
514513
GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor);

src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ protected override void DecodeWellKnownAttributeImpl(ref DecodeWellKnownAttribut
212212
| ReservedAttributes.TupleElementNamesAttribute
213213
| ReservedAttributes.NullableAttribute
214214
| ReservedAttributes.NativeIntegerAttribute
215-
| ReservedAttributes.RequiredMemberAttribute))
215+
| ReservedAttributes.RequiredMemberAttribute
216+
| ReservedAttributes.ExtensionMarkerNameAttribute))
216217
{
217218
}
218219
else if (attribute.IsTargetAttribute(AttributeDescription.DateTimeConstantAttribute))

src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,8 @@ protected override void DecodeWellKnownAttributeImpl(ref DecodeWellKnownAttribut
811811
ReservedAttributes.TupleElementNamesAttribute |
812812
ReservedAttributes.NullableAttribute |
813813
ReservedAttributes.NativeIntegerAttribute |
814-
ReservedAttributes.ScopedRefAttribute))
814+
ReservedAttributes.ScopedRefAttribute |
815+
ReservedAttributes.ExtensionMarkerNameAttribute))
815816
{
816817
}
817818
else if (attribute.IsTargetAttribute(AttributeDescription.AllowNullAttribute))

src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,11 @@ protected sealed override void DecodeWellKnownAttributeImpl(ref DecodeWellKnownA
350350
{
351351
arguments.GetOrCreateData<CommonEventWellKnownAttributeData>().HasSpecialNameAttribute = true;
352352
}
353-
else if (ReportExplicitUseOfReservedAttributes(in arguments, ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute | ReservedAttributes.TupleElementNamesAttribute))
353+
else if (ReportExplicitUseOfReservedAttributes(in arguments,
354+
ReservedAttributes.NullableAttribute
355+
| ReservedAttributes.NativeIntegerAttribute
356+
| ReservedAttributes.TupleElementNamesAttribute
357+
| ReservedAttributes.ExtensionMarkerNameAttribute))
354358
{
355359
}
356360
else if (attribute.IsTargetAttribute(AttributeDescription.ExcludeFromCodeCoverageAttribute))

src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5839,7 +5839,7 @@ private void AddAccessorIfAvailable(ArrayBuilder<Symbol> symbols, MethodSymbol?
58395839
{
58405840
if (IsExtension)
58415841
{
5842-
// PROTOTYPE: Figure out how to calculate and emit this for extensions.
5842+
// Tracked by https://github.com/dotnet/roslyn/issues/78828 : nullability, figure out how to calculate and emit this for extensions.
58435843
// We probably should do that per grouping type. Leaving as is should be fine too, I think.
58445844
// Otherwise, marker method should be processed explicitly because it is not among members.
58455845
return null;

0 commit comments

Comments
 (0)