@@ -21,16 +21,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
2121{
2222 internal sealed class ExtensionGroupingInfo
2323 {
24- /// <summary>
25- /// Extension block symbols declared in a class are grouped by their corresponding grouping type metadata name (top level key),
26- /// then grouped by their corresponding extension marker type metadata name (the secondary key used by MultiDictionary).
27- /// <see cref="SourceNamedTypeSymbol"/>s are the extension blocks.
28- /// </summary>
29- private readonly Dictionary < string , MultiDictionary < string , SourceNamedTypeSymbol > > _groupingMap ;
30- private ImmutableArray < ExtensionGroupingType > _lazyGroupingTypes ;
24+ private readonly ImmutableArray < ExtensionGroupingType > _groupingTypes ;
3125
3226 public ExtensionGroupingInfo ( SourceMemberContainerTypeSymbol container )
3327 {
28+ // Extension block symbols declared in a class are grouped by their corresponding grouping type metadata name (top level key),
29+ // then grouped by their corresponding extension marker type metadata name (the secondary key used by MultiDictionary).
30+ // SourceNamedTypeSymbols are the extension blocks.
3431 var groupingMap = new Dictionary < string , MultiDictionary < string , SourceNamedTypeSymbol > > ( EqualityComparer < string > . Default ) ;
3532
3633 foreach ( var type in container . GetTypeMembers ( "" ) )
@@ -54,7 +51,16 @@ public ExtensionGroupingInfo(SourceMemberContainerTypeSymbol container)
5451 markerMap . Add ( sourceNamedType . ExtensionMarkerName , sourceNamedType ) ;
5552 }
5653
57- _groupingMap = groupingMap ;
54+ var builder = ArrayBuilder < ExtensionGroupingType > . GetInstance ( groupingMap . Count ) ;
55+
56+ foreach ( KeyValuePair < string , MultiDictionary < string , SourceNamedTypeSymbol > > pair in groupingMap )
57+ {
58+ builder . Add ( new ExtensionGroupingType ( pair . Key , pair . Value ) ) ;
59+ }
60+
61+ builder . Sort ( ) ;
62+
63+ _groupingTypes = builder . ToImmutableAndFree ( ) ;
5864 AssertInvariants ( container ) ;
5965 }
6066
@@ -94,21 +100,7 @@ private void AssertInvariants(SourceMemberContainerTypeSymbol container)
94100
95101 public ImmutableArray < Cci . INestedTypeDefinition > GetGroupingTypes ( )
96102 {
97- if ( _lazyGroupingTypes . IsDefault )
98- {
99- var builder = ArrayBuilder < ExtensionGroupingType > . GetInstance ( _groupingMap . Count ) ;
100-
101- foreach ( KeyValuePair < string , MultiDictionary < string , SourceNamedTypeSymbol > > pair in _groupingMap )
102- {
103- builder . Add ( new ExtensionGroupingType ( pair . Key , pair . Value ) ) ;
104- }
105-
106- builder . Sort ( ) ;
107-
108- ImmutableInterlocked . InterlockedInitialize ( ref _lazyGroupingTypes , builder . ToImmutableAndFree ( ) ) ;
109- }
110-
111- return ImmutableArray < Cci . INestedTypeDefinition > . CastUp ( _lazyGroupingTypes ) ;
103+ return ImmutableArray < Cci . INestedTypeDefinition > . CastUp ( _groupingTypes ) ;
112104 }
113105
114106 public Cci . ITypeDefinition GetCorrespondingMarkerType ( SynthesizedExtensionMarker markerMethod )
@@ -119,13 +111,12 @@ public Cci.ITypeDefinition GetCorrespondingMarkerType(SynthesizedExtensionMarker
119111 private ExtensionMarkerType GetCorrespondingMarkerType ( SourceNamedTypeSymbol extension )
120112 {
121113 Debug . Assert ( extension . IsExtension ) ;
122- GetGroupingTypes ( ) ;
123114
124115 // Tracked by https://github.com/dotnet/roslyn/issues/78827 : Optimize lookup with side dictionaries?
125116 var groupingName = extension . ExtensionGroupingName ;
126117 var markerName = extension . ExtensionMarkerName ;
127118
128- foreach ( var groupingType in _lazyGroupingTypes )
119+ foreach ( var groupingType in _groupingTypes )
129120 {
130121 if ( groupingType . Name != groupingName )
131122 {
@@ -180,12 +171,11 @@ public Cci.TypeMemberVisibility GetCorrespondingMarkerMethodVisibility(Synthesiz
180171 public Cci . ITypeDefinition GetCorrespondingGroupingType ( SourceNamedTypeSymbol extension )
181172 {
182173 Debug . Assert ( extension . IsExtension ) ;
183- GetGroupingTypes ( ) ;
184174
185175 // Tracked by https://github.com/dotnet/roslyn/issues/78827 : Optimize lookup with a side dictionary?
186176 var groupingName = extension . ExtensionGroupingName ;
187177
188- foreach ( var groupingType in _lazyGroupingTypes )
178+ foreach ( var groupingType in _groupingTypes )
189179 {
190180 if ( groupingType . Name == groupingName )
191181 {
@@ -210,8 +200,7 @@ internal ImmutableArray<SourceNamedTypeSymbol> GetMergedExtensions(SourceNamedTy
210200 /// </summary>
211201 internal IEnumerable < ImmutableArray < SourceNamedTypeSymbol > > EnumerateMergedExtensionBlocks ( )
212202 {
213- GetGroupingTypes ( ) ;
214- foreach ( var groupingType in _lazyGroupingTypes )
203+ foreach ( var groupingType in _groupingTypes )
215204 {
216205 foreach ( var markerType in groupingType . ExtensionMarkerTypes )
217206 {
@@ -436,10 +425,9 @@ static void substituteConstraintTypes(ImmutableArray<TypeWithAnnotations> types,
436425 /// </summary>
437426 internal void CheckSignatureCollisions ( BindingDiagnosticBag diagnostics )
438427 {
439- GetGroupingTypes ( ) ;
440428 PooledHashSet < SourceNamedTypeSymbol > ? alreadyReportedExtensions = null ;
441429
442- foreach ( ExtensionGroupingType groupingType in _lazyGroupingTypes )
430+ foreach ( ExtensionGroupingType groupingType in _groupingTypes )
443431 {
444432 checkCollisions ( enumerateExtensionsInGrouping ( groupingType ) , HaveSameILSignature , ref alreadyReportedExtensions , diagnostics ) ;
445433 }
@@ -691,7 +679,7 @@ private sealed class ExtensionGroupingType : ExtensionGroupingOrMarkerType, ICom
691679 {
692680 private readonly string _name ;
693681 public readonly ImmutableArray < ExtensionMarkerType > ExtensionMarkerTypes ;
694- private readonly ImmutableArray < ExtensionGroupingTypeTypeParameter > _typeParameters ;
682+ private ImmutableArray < ExtensionGroupingTypeTypeParameter > _lazyTypeParameters ;
695683
696684 public ExtensionGroupingType ( string name , MultiDictionary < string , SourceNamedTypeSymbol > extensionMarkerTypes )
697685 {
@@ -706,10 +694,6 @@ public ExtensionGroupingType(string name, MultiDictionary<string, SourceNamedTyp
706694
707695 builder . Sort ( ) ;
708696 ExtensionMarkerTypes = builder . ToImmutableAndFree ( ) ;
709-
710- _typeParameters = ExtensionMarkerTypes [ 0 ] . UnderlyingExtensions [ 0 ] . Arity != 0 ?
711- ( ( INestedTypeDefinition ) ExtensionMarkerTypes [ 0 ] . UnderlyingExtensions [ 0 ] . GetCciAdapter ( ) ) . GenericParameters . SelectAsArray ( static ( p , @this ) => new ExtensionGroupingTypeTypeParameter ( @this , p ) , this ) :
712- [ ] ;
713697 }
714698
715699 int IComparable < ExtensionGroupingType > . CompareTo ( ExtensionGroupingType ? other )
@@ -718,7 +702,21 @@ int IComparable<ExtensionGroupingType>.CompareTo(ExtensionGroupingType? other)
718702 return ExtensionMarkerTypes [ 0 ] . CompareTo ( other . ExtensionMarkerTypes [ 0 ] ) ;
719703 }
720704
721- protected override IEnumerable < IGenericTypeParameter > GenericParameters => _typeParameters ;
705+ protected override IEnumerable < IGenericTypeParameter > GenericParameters
706+ {
707+ get
708+ {
709+ if ( _lazyTypeParameters . IsDefault )
710+ {
711+ var typeParameters = ExtensionMarkerTypes [ 0 ] . UnderlyingExtensions [ 0 ] . Arity != 0 ?
712+ ( ( INestedTypeDefinition ) ExtensionMarkerTypes [ 0 ] . UnderlyingExtensions [ 0 ] . GetCciAdapter ( ) ) . GenericParameters . SelectAsArray ( static ( p , @this ) => new ExtensionGroupingTypeTypeParameter ( @this , p ) , this ) :
713+ [ ] ;
714+ ImmutableInterlocked . InterlockedInitialize ( ref _lazyTypeParameters , typeParameters ) ;
715+ }
716+
717+ return _lazyTypeParameters ;
718+ }
719+ }
722720
723721 protected override ushort GenericParameterCount => ( ushort ) ExtensionMarkerTypes [ 0 ] . UnderlyingExtensions [ 0 ] . Arity ;
724722
@@ -841,7 +839,7 @@ private sealed class ExtensionMarkerType : ExtensionGroupingOrMarkerType, ICompa
841839 public readonly ExtensionGroupingType GroupingType ;
842840 private readonly string _name ;
843841 public readonly ImmutableArray < SourceNamedTypeSymbol > UnderlyingExtensions ;
844- private readonly ImmutableArray < InheritedTypeParameter > _typeParameters ;
842+ private ImmutableArray < InheritedTypeParameter > _lazyTypeParameters ;
845843
846844 public ExtensionMarkerType ( ExtensionGroupingType groupingType , string name , MultiDictionary < string , SourceNamedTypeSymbol > . ValueSet extensions )
847845 {
@@ -852,10 +850,6 @@ public ExtensionMarkerType(ExtensionGroupingType groupingType, string name, Mult
852850 builder . AddRange ( extensions ) ;
853851 builder . Sort ( LexicalOrderSymbolComparer . Instance ) ;
854852 UnderlyingExtensions = builder . ToImmutableAndFree ( ) ;
855-
856- _typeParameters = UnderlyingExtensions [ 0 ] . Arity != 0 ?
857- ( ( INestedTypeDefinition ) UnderlyingExtensions [ 0 ] . GetCciAdapter ( ) ) . GenericParameters . SelectAsArray ( static ( p , @this ) => new InheritedTypeParameter ( p . Index , @this , p ) , this ) :
858- [ ] ;
859853 }
860854
861855 public int CompareTo ( ExtensionMarkerType ? other )
@@ -864,7 +858,21 @@ public int CompareTo(ExtensionMarkerType? other)
864858 return LexicalOrderSymbolComparer . Instance . Compare ( UnderlyingExtensions [ 0 ] , other . UnderlyingExtensions [ 0 ] ) ;
865859 }
866860
867- protected override IEnumerable < IGenericTypeParameter > GenericParameters => _typeParameters ;
861+ protected override IEnumerable < IGenericTypeParameter > GenericParameters
862+ {
863+ get
864+ {
865+ if ( _lazyTypeParameters . IsDefault )
866+ {
867+ var typeParameters = UnderlyingExtensions [ 0 ] . Arity != 0 ?
868+ ( ( INestedTypeDefinition ) UnderlyingExtensions [ 0 ] . GetCciAdapter ( ) ) . GenericParameters . SelectAsArray ( static ( p , @this ) => new InheritedTypeParameter ( p . Index , @this , p ) , this ) :
869+ [ ] ;
870+ ImmutableInterlocked . InterlockedInitialize ( ref _lazyTypeParameters , typeParameters ) ;
871+ }
872+
873+ return _lazyTypeParameters ;
874+ }
875+ }
868876
869877 protected override ushort GenericParameterCount => ( ushort ) UnderlyingExtensions [ 0 ] . Arity ;
870878
0 commit comments