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

Sholtee / proxygen / 1009

20 Apr 2025 03:04PM UTC coverage: 91.635% (-0.009%) from 91.644%
1009

push

appveyor

Sholtee
introduce CurrentMember.GetImplementedInterfaceMethod() method

5017 of 5475 relevant lines covered (91.63%)

0.92 hits per line

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

92.98
/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.Diagnostics;
9
using System.Linq;
10
using System.Linq.Expressions;
11
using System.Reflection;
12

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

17
    internal static class MethodInfoExtensions
18
    {
19
        public static AccessModifiers GetAccessModifiers(this MethodBase src) => src switch
1✔
20
        {
1✔
21
            _ when src.IsFamily => AccessModifiers.Protected,
1✔
22
            _ when src.IsAssembly => AccessModifiers.Internal,
1✔
23
            _ when src.IsFamilyOrAssembly => AccessModifiers.Protected | AccessModifiers.Internal,
1✔
24
            _ when src.IsFamilyAndAssembly => AccessModifiers.Protected | AccessModifiers.Private,
1✔
25
            _ when src.IsPublic => AccessModifiers.Public,
1✔
26
            _ when src.IsPrivate && src.GetImplementedInterfaceMethods().Any() => AccessModifiers.Explicit,
1✔
27
            _ when src.IsPrivate => AccessModifiers.Private,
1✔
28
            _ => throw new InvalidOperationException(Resources.UNDETERMINED_ACCESS_MODIFIER)
×
29
        };
1✔
30

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

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

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

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

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

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

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

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

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

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

83
            Debug.Assert(!method.IsGenericMethod || method.IsGenericMethodDefinition, "The original method cannot be closed generic");
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.GetParameters().Select(static p => p.ParameterType)];
1✔
91

92
            foreach (Type baseType in method.ReflectedType.GetBaseTypes())
1✔
93
            {
1✔
94
                //
95
                // baseType.GetMethod(method.Name, types: paramz) won't work for generic methods
96
                //
97

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

103
                    if (baseMethod.IsGenericMethod)
1✔
104
                    {
1✔
105
                        Debug.Assert(baseMethod.IsGenericMethodDefinition, "The inspected method cannot be closed generic");
1✔
106

107
                        //
108
                        // We don't need to compare the generic parameters, just check the arity
109
                        //
110

111
                        if (!method.IsGenericMethod || baseMethod.GetGenericArguments().Length != method.GetGenericArguments().Length)
×
112
                            continue;
×
113
                    }
1✔
114

115
                    if (baseMethod.GetParameters().Select(static p => p.ParameterType).SequenceEqual(paramz, TypeComparer.Instance))
1✔
116
                        return baseMethod;
1✔
117
                }
1✔
118
            }
1✔
119

120
            return null;
1✔
121
        }
1✔
122

123
        //
124
        // Similar logic is provided by Solti.Utils.Primitives, too. But we don't want to ship
125
        // that library with our source generator, so reimplement it.
126
        //
127

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

130
        public static bool IsVirtual(this MethodBase method) =>
131
            method.IsVirtual && !method.IsFinal && !method.ReflectedType.IsInterface;
1✔
132
    }
133
}
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