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

NetFabric / NetFabric.CodeAnalysis / 6130084901

09 Sep 2023 09:14AM UTC coverage: 83.158% (+0.2%) from 82.932%
6130084901

push

github

web-flow
Fixes (#27)

227 of 266 branches covered (0.0%)

Branch coverage included in aggregate %.

661 of 661 new or added lines in 31 files covered. (100.0%)

642 of 779 relevant lines covered (82.41%)

18.46 hits per line

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

95.83
/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
    /// <param name="enumerableInfo">If methods returns <c>true</c>, contains information on the methods 'foreach' will use to enumerate.</param>
15
    /// <returns><c>true</c> if 'foreach' considers <see cref="System.Type"/> to be enumerable; otherwise, <c>false</c>.</returns>
16
    public static bool IsEnumerable(this Type type, [NotNullWhen(true)] out EnumerableInfo? enumerableInfo)
17
        => IsEnumerable(type, out enumerableInfo, out _);
×
18

19
    /// <summary>
20
    /// Gets a value indicating whether 'foreach' considers <see cref="System.Type"/> to be enumerable.
21
    /// </summary>
22
    /// <param name="type">The <see cref="System.Type"/> to test.</param>
23
    /// <param name="enumerableInfo">If methods returns <c>true</c>, contains information on the methods 'foreach' will use to enumerate.</param>
24
    /// <param name="errors">Gets information on what error caused the method to return <c>false</c>.</param>
25
    /// <returns><c>true</c> if 'foreach' considers <see cref="System.Type"/> to be enumerable; otherwise, <c>false</c>.</returns>
26
    public static bool IsEnumerable(this Type type,
27
        [NotNullWhen(true)] out EnumerableInfo? enumerableInfo,
28
        out Errors errors)
29
    {
30
        var forEachUsesIndexer = type.IsArray || type.IsSpanOrReadOnlySpan();
77✔
31

32
        if (!type.IsInterface)
77✔
33
        {
34
            var getEnumerator = type.GetPublicInstanceMethod(nameof(IEnumerable.GetEnumerator), Type.EmptyTypes);
74✔
35
            if (getEnumerator is not null)
74✔
36
            {
37
                var enumeratorType = getEnumerator.ReturnType;
59✔
38
                if (enumeratorType.IsInterface)
59✔
39
                {
40
                    if (enumeratorType.ImplementsInterface(typeof(IEnumerator<>), out var enumeratorGenericArguments))
8✔
41
                    {
42
                        enumerableInfo = new EnumerableInfo(
1✔
43
                            forEachUsesIndexer,
1✔
44
                            getEnumerator,
1✔
45
                            new EnumeratorInfo(
1✔
46
                                current: typeof(IEnumerator<>).MakeGenericType(enumeratorGenericArguments[0]).GetPublicInstanceDeclaredOnlyReadProperty(nameof(IEnumerator<int>.Current))!,
1✔
47
                                moveNext: typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(nameof(IEnumerator.MoveNext), Type.EmptyTypes)!)
1✔
48
                            {
1✔
49
                                Reset = typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(NameOf.Reset, Type.EmptyTypes),
1✔
50
                                Dispose = typeof(IDisposable).GetPublicInstanceDeclaredOnlyMethod(NameOf.Dispose, Type.EmptyTypes),
1✔
51
                                IsGenericsEnumeratorInterface = true,
1✔
52
                            }
1✔
53
                        );                            
1✔
54
                    }
55
                    else if(enumeratorType.ImplementsInterface(typeof(IEnumerator), out _))
7!
56
                    {
57
                        _ = enumeratorType.IsDisposable(out var dispose, out _);
7✔
58
                        enumerableInfo = new EnumerableInfo(
7✔
59
                            forEachUsesIndexer,
7✔
60
                            getEnumerator,
7✔
61
                            new EnumeratorInfo(
7✔
62
                                current: typeof(IEnumerator).GetPublicInstanceDeclaredOnlyReadProperty(nameof(IEnumerator<int>.Current))!,
7✔
63
                                moveNext: typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(nameof(IEnumerator.MoveNext), Type.EmptyTypes)!)
7✔
64
                            {
7✔
65
                                Reset = typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(NameOf.Reset, Type.EmptyTypes),
7✔
66
                                Dispose = dispose,
7✔
67
                                IsEnumeratorInterface = true,
7✔
68
                            }
7✔
69
                        );                            
7✔
70
                    }
71
                    else
72
                    {
73
                        enumerableInfo = default;
×
74
                        errors = Errors.MissingCurrent;
×
75
                        return false;
×
76
                    }
77
                }
78
                else
79
                {
80
                    var current = enumeratorType.GetPublicInstanceReadProperty(nameof(IEnumerator.Current));
51✔
81
                    if (current is null)
51✔
82
                    {
83
                        enumerableInfo = default;
2✔
84
                        errors = Errors.MissingCurrent;
2✔
85
                        return false;
2✔
86
                    }
87

88
                    var moveNext =
49✔
89
                        enumeratorType.GetPublicInstanceMethod(nameof(IEnumerator.MoveNext), Type.EmptyTypes);
49✔
90
                    if (moveNext is null)
49✔
91
                    {
92
                        enumerableInfo = default;
1✔
93
                        errors = Errors.MissingMoveNext;
1✔
94
                        return false;
1✔
95
                    }
96

97
                    var reset = enumeratorType.GetPublicInstanceMethod(NameOf.Reset, Type.EmptyTypes);
48✔
98
                    _ = enumeratorType.IsDisposable(out var dispose, out var isByRefLike);
48✔
99
                    enumerableInfo = new EnumerableInfo(
48✔
100
                        forEachUsesIndexer,
48✔
101
                        getEnumerator,
48✔
102
                        new EnumeratorInfo(current, moveNext)
48✔
103
                        {
48✔
104
                            Reset = reset,
48✔
105
                            Dispose = dispose,
48✔
106
                            IsValueType = getEnumerator.ReturnType.IsValueType,
48✔
107
                            IsByRefLike = isByRefLike,
48✔
108
                        }
48✔
109
                    );
48✔
110
                }
111

112
                errors = Errors.None;
56✔
113
                return true;
56✔
114
            }
115
        }
116

117
        if (type.ImplementsInterface(typeof(IEnumerable<>), out var enumerableGenericArguments))
18✔
118
        {
119
            var genericType = typeof(IEnumerable<>).MakeGenericType(enumerableGenericArguments[0]);
9✔
120
            var getEnumerator = genericType.GetPublicInstanceDeclaredOnlyMethod(nameof(IEnumerable<int>.GetEnumerator), Type.EmptyTypes)!;
9✔
121
            enumerableInfo = new EnumerableInfo(
9✔
122
                forEachUsesIndexer,
9✔
123
                getEnumerator,
9✔
124
                new EnumeratorInfo(
9✔
125
                    current: typeof(IEnumerator<>).MakeGenericType(enumerableGenericArguments[0]).GetPublicInstanceDeclaredOnlyReadProperty(nameof(IEnumerator<int>.Current))!,
9✔
126
                    moveNext: typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(nameof(IEnumerator.MoveNext), Type.EmptyTypes)!)
9✔
127
                    {
9✔
128
                        Reset = typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(NameOf.Reset, Type.EmptyTypes),
9✔
129
                        Dispose = typeof(IDisposable).GetPublicInstanceDeclaredOnlyMethod(NameOf.Dispose, Type.EmptyTypes),
9✔
130
                        IsGenericsEnumeratorInterface = true,
9✔
131
                    }
9✔
132
            );
9✔
133
            errors = Errors.None; 
9✔
134
            return true;
9✔
135
        }
136

137
        if (type.ImplementsInterface(typeof(IEnumerable), out _))
9✔
138
        {
139
            var getEnumerator = typeof(IEnumerable).GetPublicInstanceDeclaredOnlyMethod(nameof(IEnumerable.GetEnumerator), Type.EmptyTypes)!;
8✔
140
            _ = getEnumerator.ReturnType.IsDisposable(out var dispose, out _);
8✔
141
            enumerableInfo = new EnumerableInfo(
8✔
142
                forEachUsesIndexer,
8✔
143
                getEnumerator,
8✔
144
                new EnumeratorInfo(
8✔
145
                    current: typeof(IEnumerator).GetPublicInstanceDeclaredOnlyReadProperty(nameof(IEnumerator.Current))!,
8✔
146
                    moveNext: typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(nameof(IEnumerator.MoveNext), Type.EmptyTypes)!)
8✔
147
                    {
8✔
148
                        Reset = typeof(IEnumerator).GetPublicInstanceDeclaredOnlyMethod(NameOf.Reset, Type.EmptyTypes),
8✔
149
                        Dispose = dispose,
8✔
150
                        IsEnumeratorInterface = true,
8✔
151
                    }
8✔
152
            );
8✔
153
            errors = Errors.None; 
8✔
154
            return true;
8✔
155
        }
156

157
        enumerableInfo = default;
1✔
158
        errors = Errors.MissingGetEnumerator;
1✔
159
        return false;
1✔
160
    }
161
}
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