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

Sholtee / proxygen / 958

03 Apr 2025 03:53AM UTC coverage: 90.273% (-0.01%) from 90.283%
958

push

appveyor

Sholtee
throw specific exceptions

4835 of 5356 relevant lines covered (90.27%)

0.9 hits per line

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

94.37
/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
            _ => throw new InvalidOperationException(Resources.UNDETERMINED_ACCESS_MODIFIER)
×
28
        };
1✔
29

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

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

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

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

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

56
                if (iface.IsGenericType && reflectedType.IsArray)
1✔
57
                    continue;
×
58

59
                InterfaceMapping mapping = reflectedType.GetInterfaceMap(iface);
1✔
60

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

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

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

82
            if (method.IsGenericMethod)
1✔
83
                method = method.GetGenericMethodDefinition();
1✔
84

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

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

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

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

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

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

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

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

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

130
                    return baseMethod;
1✔
131
                    next:;
1✔
132
                }
1✔
133
            }
1✔
134
            return null;
1✔
135
        }
1✔
136

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

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

144
        public static bool IsVirtual(this MethodBase method) =>
145
            method.IsVirtual && !method.IsFinal && !method.ReflectedType.IsInterface;
1✔
146
    }
147
}
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

© 2026 Coveralls, Inc