@@ -44,8 +44,6 @@ public static (EquatableArray<MockMemberModel> Methods, EquatableArray<MockMembe
4444 seenMethods , seenFullMethods , seenProperties , seenEvents , ref memberIdCounter ) ;
4545 }
4646
47- var collectStaticAbstractFromInterfaces = ShouldCollectStaticAbstractFromInterfaces ( typeSymbol ) ;
48-
4947 foreach ( var iface in interfaces )
5048 {
5149 string ? explicitInterfaceName = null ;
@@ -55,10 +53,7 @@ public static (EquatableArray<MockMemberModel> Methods, EquatableArray<MockMembe
5553 {
5654 if ( member . IsStatic )
5755 {
58- if ( member . IsAbstract && collectStaticAbstractFromInterfaces )
59- {
60- CollectStaticAbstractMember ( member , interfaceFqn , methods , properties , events , seenMethods , seenProperties , seenEvents , ref memberIdCounter ) ;
61- }
56+ TryCollectStaticAbstractFromInterface ( member , typeSymbol , interfaceFqn , methods , properties , events , seenMethods , seenProperties , seenEvents , ref memberIdCounter ) ;
6257 continue ;
6358 }
6459
@@ -193,8 +188,6 @@ public static (EquatableArray<MockMemberModel> Methods, EquatableArray<MockMembe
193188 ? new [ ] { typeSymbol } . Concat ( typeSymbol . AllInterfaces )
194189 : typeSymbol . AllInterfaces . AsEnumerable ( ) ;
195190
196- var collectStaticAbstractFromInterfaces = ShouldCollectStaticAbstractFromInterfaces ( typeSymbol ) ;
197-
198191 foreach ( var iface in interfaces )
199192 {
200193 var interfaceFqn = iface . GetFullyQualifiedName ( ) ;
@@ -203,10 +196,7 @@ public static (EquatableArray<MockMemberModel> Methods, EquatableArray<MockMembe
203196 {
204197 if ( member . IsStatic )
205198 {
206- if ( member . IsAbstract && collectStaticAbstractFromInterfaces )
207- {
208- CollectStaticAbstractMember ( member , interfaceFqn , methods , properties , events , seenMethods , seenProperties , seenEvents , ref memberIdCounter ) ;
209- }
199+ TryCollectStaticAbstractFromInterface ( member , typeSymbol , interfaceFqn , methods , properties , events , seenMethods , seenProperties , seenEvents , ref memberIdCounter ) ;
210200 continue ;
211201 }
212202
@@ -1075,16 +1065,39 @@ private static string EscapeIdentifier(string name) =>
10751065 }
10761066
10771067 /// <summary>
1078- /// Single source of truth for whether a member-discovery loop should collect static-abstract
1079- /// interface members for the given target. Class targets already provide the concrete static
1080- /// impl that satisfies any static-abstract interface members; emitting a bridge interface for
1081- /// them would produce CS0527 (class in interface list) and CS0540 (explicit interface impl on
1082- /// a type that doesn't list the interface). Any new collection loop over interface members
1083- /// MUST gate static-abstract collection through this helper.
1068+ /// Internal predicate consumed only by <see cref="TryCollectStaticAbstractFromInterface"/>.
1069+ /// Class targets already provide the concrete static impl that satisfies any static-abstract
1070+ /// interface members; emitting a bridge interface for them would produce CS0527 (class in
1071+ /// interface list) and CS0540 (explicit interface impl on a type that doesn't list the
1072+ /// interface). Centralised here so no caller can bypass the gate by accident.
10841073 /// </summary>
10851074 private static bool ShouldCollectStaticAbstractFromInterfaces ( ITypeSymbol typeSymbol )
10861075 => typeSymbol . TypeKind != TypeKind . Class ;
10871076
1077+ /// <summary>
1078+ /// Gated entry point used by every interface-member discovery loop for static members.
1079+ /// Derives the static-abstract collection flag from <paramref name="typeSymbol"/> internally
1080+ /// so that adding a future loop cannot silently re-introduce the #5677 regression — the
1081+ /// only way to collect a static-abstract member is through this helper.
1082+ /// </summary>
1083+ private static void TryCollectStaticAbstractFromInterface (
1084+ ISymbol member ,
1085+ ITypeSymbol typeSymbol ,
1086+ string interfaceFqn ,
1087+ List < MockMemberModel > methods ,
1088+ List < MockMemberModel > properties ,
1089+ List < MockEventModel > events ,
1090+ Dictionary < string , ( int Index , ITypeSymbol ? ReturnType ) > seenMethods ,
1091+ Dictionary < string , int ? > seenProperties ,
1092+ HashSet < string > seenEvents ,
1093+ ref int memberIdCounter )
1094+ {
1095+ if ( ! member . IsAbstract ) return ;
1096+ if ( ! ShouldCollectStaticAbstractFromInterfaces ( typeSymbol ) ) return ;
1097+
1098+ CollectStaticAbstractMember ( member , interfaceFqn , methods , properties , events , seenMethods , seenProperties , seenEvents , ref memberIdCounter ) ;
1099+ }
1100+
10881101 /// <summary>
10891102 /// Returns true when the given type symbol is an interface that contains static abstract members
10901103 /// (directly or via inherited interfaces) without a most specific implementation.
0 commit comments