Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,9 @@ public bool Equals(MethodSymbol? x, MethodSymbol? y)
}

var xExtension = x.OriginalDefinition.ContainingType;
var xGroupingKey = ((SourceNamedTypeSymbol)xExtension).GetExtensionGroupingMetadataName();
var xGroupingKey = ((SourceNamedTypeSymbol)xExtension).ExtensionGroupingName;
var yExtension = y.OriginalDefinition.ContainingType;
var yGroupingKey = ((SourceNamedTypeSymbol)yExtension).GetExtensionGroupingMetadataName();
var yGroupingKey = ((SourceNamedTypeSymbol)yExtension).ExtensionGroupingName;

if (!xGroupingKey.Equals(yGroupingKey))
{
Expand Down Expand Up @@ -293,7 +293,7 @@ public int GetHashCode(MethodSymbol op)
int result = typeComparer.GetHashCode(op.OriginalDefinition.ContainingType.ContainingType);

var extension = op.OriginalDefinition.ContainingType;
var groupingKey = ((SourceNamedTypeSymbol)extension).GetExtensionGroupingMetadataName();
var groupingKey = ((SourceNamedTypeSymbol)extension).ExtensionGroupingName;
result = Hash.Combine(result, groupingKey.GetHashCode());

foreach (var parameter in op.OriginalDefinition.AsMember(Normalize(extension)).Parameters)
Expand Down
437 changes: 270 additions & 167 deletions src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,14 @@ public override object VisitTypeParameter(TypeParameterSymbol symbol, StringBuil

public override object VisitNamedType(NamedTypeSymbol symbol, StringBuilder builder)
{
if ((object)symbol.ContainingSymbol != null && symbol.ContainingSymbol.Name.Length != 0)
Symbol containingSymbol = symbol.ContainingSymbol;
if ((object)containingSymbol != null && (containingSymbol.Name.Length != 0 || containingSymbol is NamedTypeSymbol { IsExtension: true }))
{
Visit(symbol.ContainingSymbol, builder);
Visit(containingSymbol, builder);
builder.Append('.');
}

// PROTOTYPE: Finalize the doc ID story. When we refer to a member, we probably need to use grouping type name,
// but when we refer to an extension block, we probably need to "dot" through both names.
builder.Append(symbol.IsExtension ? symbol.ExtensionName : symbol.Name);
builder.Append(symbol.IsExtension ? symbol.ExtensionGroupingName : symbol.Name);

if (symbol.Arity != 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public override object VisitNamedType(NamedTypeSymbol symbol, StringBuilder buil
{
builder.Append("T:");
PartVisitor.Instance.Visit(symbol, builder);
if (symbol.IsExtension)
{
builder.Append('.');
builder.Append(symbol.ExtensionMarkerName);
}

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ Cci.ITypeDefinition Cci.ITypeDefinitionMember.ContainingTypeDefinition
return synthesizedGlobalMethod.ContainingPrivateImplementationDetailsType;
}

// PROTOTYPE: Share logic with Cci.ITypeMemberReference.GetContainingType implementation?
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : code quality, share logic with Cci.ITypeMemberReference.GetContainingType implementation?
if (AdaptedMethodSymbol is SynthesizedExtensionMarker marker)
{
return ((SourceMemberContainerTypeSymbol)AdaptedMethodSymbol.ContainingType.ContainingType).GetExtensionGroupingInfo().GetCorrespondingMarkerType(marker);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ ITypeDefinition ITypeDefinitionMember.ContainingTypeDefinition
{
CheckDefinitionInvariant();

// PROTOTYPE: Share logic with Cci.ITypeMemberReference.GetContainingType implementation?
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : code quality, share logic with Cci.ITypeMemberReference.GetContainingType implementation?
if (AdaptedPropertySymbol.GetIsNewExtensionMember())
{
var containingType = AdaptedPropertySymbol.ContainingType;
Expand Down Expand Up @@ -249,7 +249,7 @@ ITypeReference ITypeMemberReference.GetContainingType(EmitContext context)
{
CheckDefinitionInvariant();

// PROTOTYPE: Share logic with Cci.ITypeMemberReference.GetContainingType implementation in MethodSymbolAdapter?
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : code quality, share logic with Cci.ITypeMemberReference.GetContainingType implementation in MethodSymbolAdapter?
if (AdaptedPropertySymbol.GetIsNewExtensionMember())
{
var containingType = AdaptedPropertySymbol.ContainingType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ private void AddNameAndTypeArgumentsOrParameters(INamedTypeSymbol symbol)
if (Format.CompilerInternalOptions.HasFlag(SymbolDisplayCompilerInternalOptions.UseMetadataMemberNames))
{
// PROTOTYPE: What should we output as the name here
var extensionIdentifier = underlyingTypeSymbol!.ExtensionName; // Tracked by https://github.com/dotnet/roslyn/issues/78957 : public API, use public API once it's available
var extensionIdentifier = underlyingTypeSymbol!.ExtensionGroupingName; // Tracked by https://github.com/dotnet/roslyn/issues/78957 : public API, use public API once it's available
Builder.Add(CreatePart(SymbolDisplayPartKind.ClassName, symbol, extensionIdentifier));
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ internal sealed override bool MangleName
internal sealed override bool IsFileLocal => false;
internal sealed override FileIdentifier? AssociatedFileIdentifier => null;

internal override string ExtensionName
internal override string ExtensionGroupingName
=> throw ExceptionUtilities.Unreachable();

internal override string ExtensionMarkerName
=> throw ExceptionUtilities.Unreachable();

public sealed override int Arity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ public sealed override bool IsRefLikeType
get { return false; }
}

internal override string ExtensionName
internal override string ExtensionGroupingName
=> throw ExceptionUtilities.Unreachable();

internal override string ExtensionMarkerName
=> throw ExceptionUtilities.Unreachable();

public sealed override bool IsReadOnly
Expand Down
5 changes: 4 additions & 1 deletion src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ public sealed override bool IsRefLikeType
}
}

internal override string ExtensionName
internal sealed override string ExtensionGroupingName
=> throw ExceptionUtilities.Unreachable();

internal sealed override string ExtensionMarkerName
=> throw ExceptionUtilities.Unreachable();

public sealed override bool IsReadOnly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2695,7 +2695,7 @@ public override bool IsRefLikeType
}
}

internal override string ExtensionName
internal override string ExtensionGroupingName
{
get
{
Expand All @@ -2708,6 +2708,19 @@ internal override string ExtensionName
}
Copy link
Member

@jjonescz jjonescz Jul 31, 2025

Choose a reason for hiding this comment

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

Is the prototype comment still valid? #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's removed in next PR where I also added explicit test for this scenario/path

}

internal override string ExtensionMarkerName
{
get
{
if (!IsExtension)
{
throw ExceptionUtilities.Unreachable();
}

return MetadataName;
}
}

public override bool IsReadOnly
{
get
Expand Down
10 changes: 8 additions & 2 deletions src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -509,9 +509,15 @@ public override string MetadataName
internal abstract FileIdentifier? AssociatedFileIdentifier { get; }

/// <summary>
/// For extensions, returns the synthesized identifier for the type: "&lt;E>__N".
/// For extensions, returns the synthesized identifier for the grouping type.
/// </summary>
internal abstract string ExtensionName { get; }
internal abstract string ExtensionGroupingName { get; }

/// <summary>
/// For extensions, returns the synthesized identifier for the marker type.
/// </summary>
internal abstract string ExtensionMarkerName { get; }

#nullable disable

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,12 @@ internal sealed override bool HasAsyncMethodBuilderAttribute(out TypeSymbol? bui
return false;
}

internal override string ExtensionGroupingName
=> throw ExceptionUtilities.Unreachable();

internal override string ExtensionMarkerName
=> throw ExceptionUtilities.Unreachable();

private sealed class NativeIntegerTypeMap : AbstractTypeMap
{
private readonly NativeIntegerTypeSymbol _type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,5 +471,11 @@ internal sealed override bool HasAsyncMethodBuilderAttribute(out TypeSymbol? bui
}

internal override bool HasCompilerLoweringPreserveAttribute => _underlyingType.HasCompilerLoweringPreserveAttribute;

internal override string ExtensionGroupingName
=> _underlyingType.ExtensionGroupingName;

internal override string ExtensionMarkerName
=> _underlyingType.ExtensionMarkerName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ExtensionGroupingInfo(SourceMemberContainerTypeSymbol container)
}

var sourceNamedType = (SourceNamedTypeSymbol)type;
var groupingMetadataName = sourceNamedType.GetExtensionGroupingMetadataName();
var groupingMetadataName = sourceNamedType.ExtensionGroupingName;

MultiDictionary<string, SourceNamedTypeSymbol>? markerMap;

Expand All @@ -50,7 +50,7 @@ public ExtensionGroupingInfo(SourceMemberContainerTypeSymbol container)
groupingMap.Add(groupingMetadataName, markerMap);
}

markerMap.Add(sourceNamedType.GetExtensionMarkerMetadataName(), sourceNamedType);
markerMap.Add(sourceNamedType.ExtensionMarkerName, sourceNamedType);
}

_groupingMap = groupingMap;
Expand Down Expand Up @@ -80,13 +80,14 @@ public Cci.ITypeDefinition GetCorrespondingMarkerType(SynthesizedExtensionMarker
return GetCorrespondingMarkerType((SourceNamedTypeSymbol)markerMethod.ContainingType);
}

private ExtensionMarkerType GetCorrespondingMarkerType(SourceNamedTypeSymbol type)
private ExtensionMarkerType GetCorrespondingMarkerType(SourceNamedTypeSymbol extension)
{
Debug.Assert(extension.IsExtension);
GetGroupingTypes();

// PROTOTYPE: Optimize lookup with side dictionaries?
var groupingName = type.GetExtensionGroupingMetadataName();
var markerName = type.GetExtensionMarkerMetadataName();
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : Optimize lookup with side dictionaries?
var groupingName = extension.ExtensionGroupingName;
var markerName = extension.ExtensionMarkerName;

foreach (var groupingType in _lazyGroupingTypes)
{
Expand Down Expand Up @@ -140,12 +141,13 @@ public Cci.TypeMemberVisibility GetCorrespondingMarkerMethodVisibility(Synthesiz
return result;
}

public Cci.ITypeDefinition GetCorrespondingGroupingType(SourceNamedTypeSymbol type)
public Cci.ITypeDefinition GetCorrespondingGroupingType(SourceNamedTypeSymbol extension)
{
Debug.Assert(extension.IsExtension);
GetGroupingTypes();

// PROTOTYPE: Optimize lookup with a side dictionary?
var groupingName = type.GetExtensionGroupingMetadataName();
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : Optimize lookup with a side dictionary?
var groupingName = extension.ExtensionGroupingName;

foreach (var groupingType in _lazyGroupingTypes)
{
Expand All @@ -158,6 +160,30 @@ public Cci.ITypeDefinition GetCorrespondingGroupingType(SourceNamedTypeSymbol ty
throw ExceptionUtilities.Unreachable();
}

/// <summary>
/// Given an extension block, returns all the extensions that are grouped together with it
/// </summary>
internal ImmutableArray<SourceNamedTypeSymbol> GetMergedExtensions(SourceNamedTypeSymbol extension)
{
Debug.Assert(extension.IsExtension);
return GetCorrespondingMarkerType(extension).UnderlyingExtensions;
}

/// <summary>
/// Returns all the extension blocks but grouped/merged by equivalency (ie. same marker name)
/// </summary>
internal IEnumerable<ImmutableArray<SourceNamedTypeSymbol>> EnumerateMergedExtensionBlocks()
{
GetGroupingTypes();
foreach (var groupingType in _lazyGroupingTypes)
{
foreach (var markerType in groupingType.ExtensionMarkerTypes)
{
yield return markerType.UnderlyingExtensions;
}
}
}

private abstract class ExtensionGroupingOrMarkerType : Cci.INestedTypeDefinition
{
ushort ITypeDefinition.Alignment => 0;
Expand Down Expand Up @@ -368,7 +394,7 @@ public ExtensionGroupingType(string name, MultiDictionary<string, SourceNamedTyp

foreach (var pair in extensionMarkerTypes)
{
builder.Add(new ExtensionMarkerType(this, pair.Key, pair.Value));
builder.Add(new ExtensionMarkerType(this, name: pair.Key, extensions: pair.Value));
}

builder.Sort();
Expand All @@ -393,7 +419,15 @@ int IComparable<ExtensionGroupingType>.CompareTo(ExtensionGroupingType? other)

protected override bool IsSealed => true;

protected override ITypeDefinition ContainingTypeDefinition => ExtensionMarkerTypes[0].UnderlyingExtensions[0].ContainingType!.GetCciAdapter();
protected override ITypeDefinition ContainingTypeDefinition
{
get
{
NamedTypeSymbol? containingType = ExtensionMarkerTypes[0].UnderlyingExtensions[0].ContainingType;
Debug.Assert(containingType is not null);
return containingType.GetCciAdapter();
}
}

public override string Name => _name;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,10 @@ internal sealed override bool HasCollectionBuilderAttribute(out TypeSymbol? buil
return false;
}

internal override string ExtensionName
internal override string ExtensionGroupingName
=> throw ExceptionUtilities.Unreachable();

internal override string ExtensionMarkerName
=> throw ExceptionUtilities.Unreachable();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public bool SetHasDeclaredRequiredMembers(bool value)
private ThreeState _lazyContainsExtensionMethods;
private ThreeState _lazyAnyMemberHasAttributes;

// PROTOTYPE: Move some fields into "uncommon" class field?
// Tracked by https://github.com/dotnet/roslyn/issues/78827 : Optimize by moving some fields into "uncommon" class field?
private ExtensionGroupingInfo? _lazyExtensionGroupingInfo;

#region Construction
Expand Down Expand Up @@ -2190,7 +2190,7 @@ private static void ReportMethodSignatureCollision(SourceMemberContainerTypeSymb
method2 is SourceExtensionImplementationMethodSymbol { UnderlyingMethod: var underlying2 } &&
underlying1.IsStatic == underlying2.IsStatic &&
((object)underlying1.ContainingType == underlying2.ContainingType ||
((SourceNamedTypeSymbol)underlying1.ContainingType).GetExtensionGroupingMetadataName() == ((SourceNamedTypeSymbol)underlying2.ContainingType).GetExtensionGroupingMetadataName()) &&
((SourceNamedTypeSymbol)underlying1.ContainingType).ExtensionGroupingName == ((SourceNamedTypeSymbol)underlying2.ContainingType).ExtensionGroupingName) &&
diagnostics.DiagnosticBag?.AsEnumerableWithoutResolution().Any(
static (d, arg) =>
(d.Code is (int)ErrorCode.ERR_OverloadRefKind or (int)ErrorCode.ERR_MemberAlreadyExists or
Expand Down Expand Up @@ -2387,7 +2387,7 @@ void checkMemberNameConflicts(

void checkMemberNameConflictsInExtensions(BindingDiagnosticBag diagnostics)
{
IEnumerable<IGrouping<string, NamedTypeSymbol>> extensionsByReceiverType = GetTypeMembers("").Where(static t => t.IsExtension).GroupBy(static t => ((SourceNamedTypeSymbol)t).GetExtensionGroupingMetadataName());
IEnumerable<IGrouping<string, NamedTypeSymbol>> extensionsByReceiverType = GetTypeMembers("").Where(static t => t.IsExtension).GroupBy(static t => ((SourceNamedTypeSymbol)t).ExtensionGroupingName);

foreach (var grouping in extensionsByReceiverType)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ SynthesizedEventAccessorSymbol or

if (target.GetIsNewExtensionMember())
{
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeExtensionMarkerNameAttribute(target, ((SourceNamedTypeSymbol)target.ContainingType).GetExtensionMarkerMetadataName()));
AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeExtensionMarkerNameAttribute(target, ((SourceNamedTypeSymbol)target.ContainingType).ExtensionMarkerName));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1826,7 +1826,7 @@ public override string MetadataName
get
{
return IsExtension
? GetExtensionMarkerMetadataName()
? ExtensionMarkerName
: base.MetadataName;
}
}
Expand Down
Loading