• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Sholtee / proxygen / 957

03 Apr 2025 03:49AM UTC coverage: 90.283% (+3.1%) from 87.222%
957

push

appveyor

Sholtee
fix method hash generation

4841 of 5362 relevant lines covered (90.28%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.52
/SRC/Private/Extensions/Metadata/MethodInfoExtensions.cs
1
/********************************************************************************
2
* MethodInfoExtensions.cs                                                       *
3
*                                                                               *
4
* Author: Denes Solti                                                           *
5
********************************************************************************/
6
using System;
7
using System.Collections.Generic;
8
using System.Linq;
9
using System.Linq.Expressions;
10
using System.Reflection;
11

12
namespace Solti.Utils.Proxy.Internals
13
{
14
    using Properties;
15

16
    internal static class MethodInfoExtensions
17
    {
18
        public static AccessModifiers GetAccessModifiers(this MethodBase src) => src switch
1✔
19
        {
1✔
20
            _ when src.IsFamily => AccessModifiers.Protected,
1✔
21
            _ when src.IsAssembly => AccessModifiers.Internal,
1✔
22
            _ when src.IsFamilyOrAssembly => AccessModifiers.Protected | AccessModifiers.Internal,
1✔
23
            _ when src.IsFamilyAndAssembly => AccessModifiers.Protected | AccessModifiers.Private,
1✔
24
            _ when src.IsPublic => AccessModifiers.Public,
1✔
25
            _ when src.IsPrivate && src.GetImplementedInterfaceMethods().Any() => AccessModifiers.Explicit,
1✔
26
            _ when src.IsPrivate => AccessModifiers.Private,
1✔
27
            #pragma warning disable CA2201 // In theory we should never reach here.
1✔
28
            _ => throw new Exception(Resources.UNDETERMINED_ACCESS_MODIFIER)
×
29
            #pragma warning restore CA2201
1✔
30
        };
1✔
31

32
        public static IEnumerable<Type> GetDeclaringInterfaces(this MethodBase src) => src.ReflectedType.IsInterface
1✔
33
            ? Array.Empty<Type>()
1✔
34
            : src
1✔
35
                .GetImplementedInterfaceMethods()
1✔
36
                .Select(static m => m.ReflectedType);
1✔
37

38
        public static IEnumerable<MethodBase> GetImplementedInterfaceMethods(this MethodBase src)
39
        {
1✔
40
            //
41
            // As of C# 11 interfaces may have static abstract methods... We don't deal with
42
            // the implementors.
43
            //
44

45
            if (src.IsStatic || src is not MethodInfo method /*ctor*/)
1✔
46
                yield break;
1✔
47

48
            Type reflectedType = src.ReflectedType;
1✔
49
            if (reflectedType.IsInterface)
1✔
50
                yield break;
1✔
51

52
            foreach (Type iface in reflectedType.GetInterfaces())
1✔
53
            {
1✔
54
                //
55
                // https://docs.microsoft.com/en-us/dotnet/api/system.type.getinterfacemap?view=netcore-3.1#exceptions
56
                //
57

58
                if (iface.IsGenericType && reflectedType.IsArray)
1✔
59
                    continue;
×
60

61
                InterfaceMapping mapping = reflectedType.GetInterfaceMap(iface);
1✔
62

63
                int? mapIndex = mapping
1✔
64
                    .TargetMethods
1✔
65
                    .IndexOf(method);
1✔
66

67
                if (mapIndex >= 0) 
1✔
68
                    yield return mapping.InterfaceMethods[mapIndex.Value];
1✔
69
            }
1✔
70
        }
1✔
71

72
        public static MethodInfo? GetOverriddenMethod(this MethodInfo method)
73
        {
1✔
74
            /*
75
            if (method.IsVirtual)
76
            {
77
                MethodInfo overriddenMethod = method.GetBaseDefinition();
78
                return overriddenMethod != method
79
                    ? overriddenMethod
80
                    : null;
81
            }
82
            */
83

84
            if (method.IsGenericMethod)
1✔
85
                method = method.GetGenericMethodDefinition();
1✔
86

87
            //
88
            // GetBaseDefinition() won't work for "new" override as well as it always return the declaring
89
            // method instead of the overridden one.
90
            //
91

92
            Type[] paramz = method
1✔
93
                .GetParameters()
1✔
94
                .Select(static p => p.ParameterType)
1✔
95
                .ToArray();
1✔
96

97
            foreach (Type baseType in method.DeclaringType.GetBaseTypes())
1✔
98
            {
1✔
99
                //
100
                // baseType.GetMethod(method.Name, types: paramz) won't for for generic methods
101
                //
102

103
                foreach(MethodInfo baseMethod in  baseType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | (method.IsStatic ? BindingFlags.Static : BindingFlags.Instance)))
1✔
104
                {
1✔
105
                    if (baseMethod.Name != method.Name)
1✔
106
                        continue;
1✔
107

108
                    if (baseMethod.IsGenericMethod)
1✔
109
                    {
1✔
110
                        if (!method.IsGenericMethod || baseMethod.GetGenericArguments().Length != method.GetGenericArguments().Length)
×
111
                            continue;
×
112

113
                        //
114
                        // We don't need to compare the generic parameters
115
                        //
116
                    }
1✔
117

118
                    ParameterInfo[] baseParamz = baseMethod.GetParameters();
1✔
119
                    if (baseParamz.Length != paramz.Length)
1✔
120
                        continue;
1✔
121

122
                    for (int i = 0; i < baseParamz.Length; i++)
1✔
123
                    {
1✔
124
                        Type
1✔
125
                            baseParam = baseParamz[i].ParameterType,
1✔
126
                            param = paramz[i];
1✔
127

128
                        if (param.IsGenericParameter ? param.GetGenericParameterIndex() != baseParam.GetGenericParameterIndex() : param != baseParam)
1✔
129
                            goto next;
1✔
130
                    }
1✔
131

132
                    return baseMethod;
1✔
133
                    next:;
1✔
134
                }
1✔
135
            }
1✔
136
            return null;
1✔
137
        }
1✔
138

139
        //
140
        // Similar logic is provided by Solti.Utils.Primitives, too. But we don't want to ship
141
        // that library with our source generator, so reimplement it.
142
        //
143

144
        public static MethodInfo ExtractFrom<T>(Expression<Action<T>> expression) => ((MethodCallExpression) expression.Body).Method;
1✔
145

146
        public static bool IsVirtual(this MethodBase method) =>
147
            method.IsVirtual && !method.IsFinal && !method.ReflectedType.IsInterface;
1✔
148
    }
149
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc