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

NetFabric / NetFabric.CodeAnalysis / 6277898578

22 Sep 2023 06:35PM UTC coverage: 73.953% (-9.2%) from 83.158%
6277898578

Pull #28

github

aalmada
Add IsIndexable
Pull Request #28: Add IsIndexable

323 of 452 branches covered (0.0%)

Branch coverage included in aggregate %.

349 of 349 new or added lines in 18 files covered. (100.0%)

648 of 861 relevant lines covered (75.26%)

20.93 hits per line

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

80.41
/NetFabric.Reflection/Reflection/TypeExtensions.IsEnumerable.cs
1
using System;
2
using System.Collections;
3
using System.Collections.Generic;
4
using System.Diagnostics.CodeAnalysis;
5

6
namespace NetFabric.Reflection;
7

8
public static partial class TypeExtensions
9
{        
10
    /// <summary>
11
    /// Gets a value indicating whether 'foreach' considers <see cref="System.Type"/> to be enumerable.
12
    /// </summary>
13
    /// <param name="type">The <see cref="System.Type"/> to test.</param>
14
    /// <returns><c>true</c> if 'foreach' considers <see cref="System.Type"/> to be enumerable; otherwise, <c>false</c>.</returns>
15
    public static bool IsEnumerable(this Type type)
16
        => IsEnumerable(type, out _, out _);
×
17

18
    /// <summary>
19
    /// Gets a value indicating whether 'foreach' considers <see cref="System.Type"/> to be enumerable.
20
    /// </summary>
21
    /// <param name="type">The <see cref="System.Type"/> to test.</param>
22
    /// <param name="enumerableInfo">If methods returns <c>true</c>, contains information on the methods 'foreach' will use to enumerate.</param>
23
    /// <returns><c>true</c> if 'foreach' considers <see cref="System.Type"/> to be enumerable; otherwise, <c>false</c>.</returns>
24
    public static bool IsEnumerable(this Type type, [NotNullWhen(true)] out EnumerableInfo? enumerableInfo)
25
        => IsEnumerable(type, out enumerableInfo, out _);
×
26

27
    /// <summary>
28
    /// Gets a value indicating whether 'foreach' considers <see cref="System.Type"/> to be enumerable.
29
    /// </summary>
30
    /// <param name="type">The <see cref="System.Type"/> to test.</param>
31
    /// <param name="enumerableInfo">If methods returns <c>true</c>, contains information on the methods 'foreach' will use to enumerate.</param>
32
    /// <param name="error">Gets information on what error caused the method to return <c>false</c>.</param>
33
    /// <returns><c>true</c> if 'foreach' considers <see cref="System.Type"/> to be enumerable; otherwise, <c>false</c>.</returns>
34
    public static bool IsEnumerable(this Type type,
35
        [NotNullWhen(true)] out EnumerableInfo? enumerableInfo,
36
        out IsEnumerableError error)
37
    {
38
        var forEachUsesIndexer = type.IsArray || type.IsSpanOrReadOnlySpan();
82✔
39
        var isGenericsEnumeratorInterface = false;
82✔
40
        var isEnumeratorInterface = false;
82✔
41

42
        var getEnumerator = type.GetPublicMethod(NameOf.GetEnumerator);
82✔
43
        if (getEnumerator is null && !type.IsInterface)
82✔
44
        {
45
            if (type.ImplementsInterface(typeof(IEnumerable<>), out var genericArguments))
15✔
46
            {
47
                getEnumerator ??= typeof(IEnumerable<>).MakeGenericType(genericArguments).GetPublicMethod(NameOf.GetEnumerator);
7✔
48
                isGenericsEnumeratorInterface = true;
7✔
49
            }
50
            else if (type.ImplementsInterface(typeof(IEnumerable), out _))
8✔
51
            {
52
                getEnumerator ??= typeof(IEnumerable).GetPublicMethod(NameOf.GetEnumerator);
7✔
53
                isEnumeratorInterface = true;
7✔
54
            }
55
        }
56
        if (getEnumerator is null)
82✔
57
        {
58
            enumerableInfo = default;
1✔
59
            error = IsEnumerableError.MissingGetEnumerator;
1✔
60
            return false;
1✔
61
        }
62

63
        var enumeratorType = getEnumerator.ReturnType;
81✔
64

65
        var current = enumeratorType.GetPublicReadProperty(NameOf.Current);
81✔
66
        var moveNext = enumeratorType.GetPublicMethod(NameOf.MoveNext);
81✔
67
        var reset = enumeratorType.GetPublicMethod(NameOf.Reset);
81✔
68

69
        if ((current is null || moveNext is null) && !type.IsInterface)
81✔
70
        {
71
            if (type.ImplementsInterface(typeof(IEnumerator<>), out var genericArguments))
3!
72
            {
73
                var interfaceType = typeof(IEnumerator<>).MakeGenericType(genericArguments);
×
74
                current ??= interfaceType.GetPublicReadProperty(NameOf.Current);
×
75
                moveNext ??= interfaceType.GetPublicMethod(NameOf.MoveNext);
×
76
            }
77
            else if (type.ImplementsInterface(typeof(IEnumerator), out _))
3!
78
            {
79
                var interfaceType = typeof(IEnumerator);
×
80
                current ??= interfaceType.GetPublicReadProperty(NameOf.Current);
×
81
                moveNext ??= interfaceType.GetPublicMethod(NameOf.MoveNext);
×
82
                reset ??= interfaceType.GetPublicMethod(NameOf.Reset);
×
83
            }
84
        }
85

86
        if (current is null)
81✔
87
        {
88
            enumerableInfo = default;
2✔
89
            error = IsEnumerableError.MissingCurrent;
2✔
90
            return false;
2✔
91
        }
92

93
        if (moveNext is null || moveNext.ReturnType != typeof(bool))
79✔
94
        {
95
            enumerableInfo = default;
2✔
96
            error = IsEnumerableError.MissingMoveNext;
2✔
97
            return false;
2✔
98
        }
99

100
        _ = enumeratorType.IsDisposable(out var dispose);
77✔
101

102
        enumerableInfo = new EnumerableInfo(
77✔
103
            forEachUsesIndexer,
77✔
104
            getEnumerator,
77✔
105
            new EnumeratorInfo(current, moveNext)
77✔
106
            {
77✔
107
                Reset = reset,
77✔
108
                Dispose = dispose,
77✔
109
                IsValueType = enumeratorType.IsValueType,
77✔
110
                IsByRefLike = enumeratorType.IsByRefLike,
77✔
111
                IsGenericsEnumeratorInterface = isGenericsEnumeratorInterface,
77✔
112
                IsEnumeratorInterface = isEnumeratorInterface,
77✔
113
            }
77✔
114
        );
77✔
115

116
        error = IsEnumerableError.None;
77✔
117
        return true;
77✔
118
    }
119
}
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