@@ -88,6 +88,8 @@ public class MethodAnalysisContext : HasCustomAttributesAndName, IMethodInfoProv
8888
8989 protected Memory < byte > ? rawMethodBody ;
9090
91+ public MethodAnalysisContext ? BaseMethod => Overrides . FirstOrDefault ( m => m . DeclaringType ? . IsInterface is false ) ;
92+
9193 /// <summary>
9294 /// The set of methods which this method overrides.
9395 /// </summary>
@@ -108,22 +110,29 @@ public virtual IEnumerable<MethodAnalysisContext> Overrides
108110
109111 return GetOverriddenMethods ( declaringTypeDefinition , vtable ) ;
110112
111- static void GetParentTypeAndSlot ( Il2CppTypeDefinition declaringTypeDefinition , int vtableIndex , out Il2CppTypeReflectionData ? parentType , out int slot )
113+ bool TryGetMethodForSlot ( TypeAnalysisContext declaringType , int slot , [ NotNullWhen ( true ) ] out MethodAnalysisContext ? method )
112114 {
113- var interfaceOffsets = declaringTypeDefinition . InterfaceOffsets ;
114- for ( var i = interfaceOffsets . Length - 1 ; i >= 0 ; i -- )
115+ if ( declaringType is GenericInstanceTypeAnalysisContext genericInstanceType )
116+ {
117+ var genericMethod = genericInstanceType . GenericType . Methods . FirstOrDefault ( m => m . Slot == slot ) ;
118+ if ( genericMethod is not null )
119+ {
120+ method = new ConcreteGenericMethodAnalysisContext ( genericMethod , genericInstanceType . GenericArguments . ToArray ( ) , [ ] ) ;
121+ return true ;
122+ }
123+ }
124+ else
115125 {
116- var interfaceOffset = interfaceOffsets [ i ] ;
117- if ( vtableIndex >= interfaceOffset . offset )
126+ var baseMethod = declaringType . Methods . FirstOrDefault ( m => m . Slot == slot ) ;
127+ if ( baseMethod is not null )
118128 {
119- slot = vtableIndex - interfaceOffsets [ i ] . offset ;
120- parentType = interfaceOffset . Type ;
121- return ;
129+ method = baseMethod ;
130+ return true ;
122131 }
123132 }
124133
125- parentType = declaringTypeDefinition . BaseType ;
126- slot = vtableIndex ;
134+ method = null ;
135+ return false ;
127136 }
128137
129138 IEnumerable < MethodAnalysisContext > GetOverriddenMethods ( Il2CppTypeDefinition declaringTypeDefinition , MetadataUsage ? [ ] vtable )
@@ -137,23 +146,29 @@ IEnumerable<MethodAnalysisContext> GetOverriddenMethods(Il2CppTypeDefinition dec
137146 if ( vtableEntry . AsMethod ( ) != Definition )
138147 continue ;
139148
140- GetParentTypeAndSlot ( declaringTypeDefinition , i , out var parentType , out var slot ) ;
141-
142- var parentTypeContext = parentType ? . ToContext ( CustomAttributeAssembly ) ;
143- if ( parentTypeContext == null )
144- continue ;
145-
146- if ( parentTypeContext is GenericInstanceTypeAnalysisContext genericInstanceType )
149+ // Normal inheritance
150+ var baseType = DeclaringType ? . BaseType ;
151+ while ( baseType is not null )
147152 {
148- var parentMethod = genericInstanceType . GenericType . Methods . FirstOrDefault ( m => m . Slot == slot ) ;
149- if ( parentMethod is not null )
150- yield return new ConcreteGenericMethodAnalysisContext ( parentMethod , genericInstanceType . GenericArguments . ToArray ( ) , [ ] ) ;
153+ if ( TryGetMethodForSlot ( baseType , i , out var method ) )
154+ {
155+ yield return method ;
156+ break ; // We only want direct overrides, not the entire inheritance chain.
157+ }
158+ baseType = baseType . BaseType ;
151159 }
152- else
160+
161+ // Interface inheritance
162+ foreach ( var interfaceOffset in declaringTypeDefinition . InterfaceOffsets )
153163 {
154- var parentMethod = parentTypeContext . Methods . FirstOrDefault ( m => m . Slot == slot ) ;
155- if ( parentMethod is not null )
156- yield return parentMethod ;
164+ if ( i >= interfaceOffset . offset )
165+ {
166+ var interfaceTypeContext = interfaceOffset . Type . ToContext ( CustomAttributeAssembly ) ;
167+ if ( interfaceTypeContext != null && TryGetMethodForSlot ( interfaceTypeContext , i - interfaceOffset . offset , out var method ) )
168+ {
169+ yield return method ;
170+ }
171+ }
157172 }
158173 }
159174 }
0 commit comments