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

Sholtee / proxygen / 871

01 Dec 2023 08:07AM UTC coverage: 94.801% (-0.04%) from 94.839%
871

push

appveyor

Sholtee
net8.0 still not supported by AppVeyor =(

2498 of 2635 relevant lines covered (94.8%)

5.59 hits per line

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

96.08
/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
6✔
19
        {
20
            _ when src.IsFamily => AccessModifiers.Protected,
6✔
21
            _ when src.IsAssembly => AccessModifiers.Internal,
6✔
22
            _ when src.IsFamilyOrAssembly => AccessModifiers.Protected | AccessModifiers.Internal,
6✔
23
            _ when src.IsFamilyAndAssembly => AccessModifiers.Protected | AccessModifiers.Private,
4✔
24
            _ when src.IsPublic => AccessModifiers.Public,
6✔
25
            _ when src.IsPrivate && src.GetImplementedInterfaceMethods().Any() => AccessModifiers.Explicit,
6✔
26
            _ when src.IsPrivate => AccessModifiers.Private,
6✔
27
            #pragma warning disable CA2201 // In theory we should never reach here.
28
            _ => throw new Exception(Resources.UNDETERMINED_ACCESS_MODIFIER)
×
29
            #pragma warning restore CA2201
30
        };
31

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

38
        public static IEnumerable<MethodBase> GetImplementedInterfaceMethods(this MethodBase src)
39
        {
6✔
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*/)
6✔
46
                yield break;
6✔
47

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

52
            foreach (Type iface in reflectedType.GetInterfaces())
6✔
53
            {
6✔
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)
6✔
59
                    continue;
×
60

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

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

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

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

84
            //
85
            // GetBaseDefinition() won't work for "new" override.
86
            //
87

88
            Type[] paramz = method
6✔
89
                .GetParameters()
90
                .Select(static p => p.ParameterType)
6✔
91
                .ToArray();
92

93
            foreach (Type baseType in method.ReflectedType.GetBaseTypes())
6✔
94
            {
6✔
95
                MethodInfo? overriddenMethod = baseType.GetMethod
6✔
96
                (
97
                    method.Name,
98
                    bindingAttr:
99
                        BindingFlags.DeclaredOnly |
100
                        (method.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) |
101
                        (method.IsStatic ? BindingFlags.Static : BindingFlags.Instance),
102
                    binder: null,
103
                    callConvention: method.CallingConvention,
104
                    types: paramz,
105
                    modifiers: null
106
                );
107
                if (overriddenMethod is not null)
6✔
108
                {
6✔
109
                    //
110
                    // The default binder searches for COMPATIBLE not exact signature match [for instance
111
                    // typeof(Object).GetMethod("Equals", new[] { typeof(/*Any type*/) }) is never null]
112
                    //
113
                    // I won't create a custom binder so +1 check...
114
                    //
115

116
                    ParameterInfo[] overriddenParamz = overriddenMethod.GetParameters();
6✔
117

118
                    bool match = true;
6✔
119
                    for (int i = 0; i < overriddenParamz.Length; i++)
6✔
120
                    {
6✔
121
                        if (overriddenParamz[i].ParameterType != paramz[i])
6✔
122
                        {
6✔
123
                            match = false;
6✔
124
                            break;
6✔
125
                        }
126
                    }
6✔
127
                    if (match)
6✔
128
                        return overriddenMethod;
6✔
129
                }
6✔
130
            }
6✔
131
            return null;
6✔
132
        }
6✔
133

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

139
        public static MethodInfo ExtractFrom<T>(Expression<Action<T>> expression) => ((MethodCallExpression) expression.Body).Method;
6✔
140
    }
141
}
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