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

NetFabric / NetFabric.CodeAnalysis / 6228495305

18 Sep 2023 10:04PM UTC coverage: 82.476% (-0.7%) from 83.158%
6228495305

Pull #28

github

aalmada
Add IsIndexable
Pull Request #28: Add IsIndexable

225 of 266 branches covered (0.0%)

Branch coverage included in aggregate %.

110 of 110 new or added lines in 11 files covered. (100.0%)

641 of 784 relevant lines covered (81.76%)

17.66 hits per line

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

87.58
/NetFabric.CodeAnalysis/ITypeSymbolExtensions.cs
1
using Microsoft.CodeAnalysis;
2
using System;
3
using System.Collections.Immutable;
4
// ReSharper disable InvertIf
5

6
namespace NetFabric.CodeAnalysis;
7

8
public static partial class ITypeSymbolExtensions
9
{
10
    
11
    /// <summary>
12
    /// Gets a value indicating whether <see cref="Microsoft.CodeAnalysis.ITypeSymbol"/> implements the given interface type.
13
    /// </summary>
14
    /// <param name="typeSymbol">The <see cref="System.Type"/> to test.</param>
15
    /// <param name="interfaceType">The interface <see cref="System.Type"/> to test.</param>
16
    /// <param name="genericArguments">If methods returns <c>true</c> and interface type is generic, contains the generic arguments of the implemented interface.</param>
17
    /// <returns><c>true</c> if <see cref="Microsoft.CodeAnalysis.ITypeSymbol"/> implements interface type; otherwise, <c>false</c>.</returns>
18
    public static bool ImplementsInterface(this ITypeSymbol typeSymbol, SpecialType interfaceType, out ImmutableArray<ITypeSymbol> genericArguments)
19
    {
20
        if (typeSymbol is INamedTypeSymbol namedTypeSymbol 
27✔
21
            && namedTypeSymbol.OriginalDefinition.SpecialType == interfaceType)
27✔
22
        {
23
            genericArguments = namedTypeSymbol.TypeArguments;
2✔
24
            return true;
2✔
25
        }
26
        
27
        // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
28
        foreach (var @interface in typeSymbol.AllInterfaces)
69✔
29
        {
30
            if (@interface.OriginalDefinition.SpecialType == interfaceType)
14✔
31
            {
32
                genericArguments = @interface.TypeArguments;
9✔
33
                return true;
9✔
34
            }
35
        }
36

37
        genericArguments = default;
16✔
38
        return false;
16✔
39
    }
40

41
    /// <summary>
42
    /// Gets a value indicating whether <see cref="Microsoft.CodeAnalysis.ITypeSymbol"/> implements the given interface type.
43
    /// </summary>
44
    /// <param name="typeSymbol">The <see cref="System.Type"/> to test.</param>
45
    /// <param name="interfaceType">The interface <see cref="System.Type"/> to test.</param>
46
    /// <param name="genericArguments">If methods returns <c>true</c> and interface type is generic, contains the generic arguments of the implemented interface.</param>
47
    /// <returns><c>true</c> if <see cref="Microsoft.CodeAnalysis.ITypeSymbol"/> implements interface type; otherwise, <c>false</c>.</returns>
48
    public static bool ImplementsInterface(this ITypeSymbol typeSymbol, INamedTypeSymbol interfaceType, out ImmutableArray<ITypeSymbol> genericArguments)
49
    {
50
        if (typeSymbol is INamedTypeSymbol namedTypeSymbol 
12✔
51
            && SymbolEqualityComparer.Default.Equals(namedTypeSymbol.OriginalDefinition, interfaceType))
12✔
52
        {
53
            genericArguments = namedTypeSymbol.TypeArguments;
1✔
54
            return true;
1✔
55
        }
56
        
57
        // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
58
        foreach (var @interface in typeSymbol.AllInterfaces)
26✔
59
        {
60
            if (SymbolEqualityComparer.Default.Equals(@interface.OriginalDefinition, interfaceType))
4✔
61
            {
62
                genericArguments = @interface.TypeArguments;
4✔
63
                return true;
4✔
64
            }
65
        }
66

67
        genericArguments = default;
7✔
68
        return false;
7✔
69
    }
70

71
    internal static IPropertySymbol? GetPublicReadIndexer(this ITypeSymbol typeSymbol, params Type[] parameterTypes)
72
    {
73
        foreach (var member in typeSymbol.GetMembers().OfType<IPropertySymbol>())
17✔
74
        {
75
            if (member.IsIndexer && 
4✔
76
                !member.IsStatic && 
4✔
77
                member.DeclaredAccessibility == Accessibility.Public && 
4✔
78
                member.GetMethod is not null && 
4✔
79
                SequenceEqual(member.Parameters, parameterTypes))
4✔
80
            {
81
                return member;
3✔
82
            }
83
        }
84

85
        if (typeSymbol.TypeKind == TypeKind.Interface)
3!
86
        {
87
            // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator
88
            foreach (var @interface in typeSymbol.AllInterfaces)
×
89
            {
90
                var property = @interface.GetPublicReadIndexer();
×
91
                if (property is not null)
×
92
                    return property;
×
93
            }
94
        }
95
        else
96
        {
97
            var baseType = typeSymbol.BaseType;
3✔
98
            if (baseType is not null)
3✔
99
                return baseType.GetPublicReadIndexer();
2✔
100
        }
101

102
        return null;
1✔
103
    }
3✔
104

105
    internal static IPropertySymbol? GetPublicReadProperty(this ITypeSymbol typeSymbol, string name)
106
    {
107
        foreach (var member in typeSymbol.GetMembers(name).OfType<IPropertySymbol>())
159✔
108
        {
109
            if (!member.IsStatic && 
37✔
110
                member.DeclaredAccessibility == Accessibility.Public && 
37✔
111
                member.GetMethod is not null)
37✔
112
                return member;
37✔
113
        }
114

115
        if (typeSymbol.TypeKind == TypeKind.Interface)
24!
116
        {
117
            // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator
118
            foreach (var @interface in typeSymbol.AllInterfaces)
×
119
            {
120
                var property = @interface.GetPublicReadProperty(name);
×
121
                if (property is not null)
×
122
                    return property;
×
123
            }
124
        }
125
        else
126
        {
127
            var baseType = typeSymbol.BaseType;
24✔
128
            if (baseType is not null)
24✔
129
                return baseType.GetPublicReadProperty(name);
16✔
130
        }
131

132
        return null;
8✔
133
    }
37✔
134

135
    internal static IMethodSymbol? GetPublicMethod(this ITypeSymbol typeSymbol, string name, params Type[] parameters)
136
    {
137
        foreach (var member in typeSymbol.GetMembers(name).OfType<IMethodSymbol>())
529✔
138
        {
139
            if (!member.IsStatic &&
99✔
140
                member.DeclaredAccessibility == Accessibility.Public &&
99✔
141
                SequenceEqual(member.Parameters, parameters))
99✔
142
            {
143
                return member;
87✔
144
            }
145
        }
146

147
        if (typeSymbol.TypeKind == TypeKind.Interface)
122✔
148
        {
149
            // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator
150
            foreach (var @interface in typeSymbol.AllInterfaces)
14✔
151
            {
152
                var method = @interface.GetPublicMethod(name, parameters);
4✔
153
                if (method is not null)
4✔
154
                    return method;
2✔
155
            }
156
        }
157
        else
158
        {
159
            var baseType = typeSymbol.BaseType;
118✔
160
            if (baseType is not null)
118✔
161
                return baseType.GetPublicMethod(name, parameters);
78✔
162
        }
163

164
        return null;
42✔
165
    }
87✔
166

167
    static bool SequenceEqual(ImmutableArray<IParameterSymbol> parameters, Type[] types)
168
    {
169
        if (parameters.Length != types.Length)
98✔
170
            return false;
8✔
171

172
        // ReSharper disable once LoopCanBeConvertedToQuery
173
        for (var index = 0; index < parameters.Length; index++)
204✔
174
        {
175
            if (parameters[index].Type.MetadataName != types[index].Name)
12!
176
                return false;
×
177
        }
178

179
        return true;
90✔
180
    }
181

182
    public static bool IsSpanOrReadOnlySpanType(this ITypeSymbol typeSymbol)
183
    {
184
        if (typeSymbol.Name == "Span" || typeSymbol.Name == "ReadOnlySpan")
23✔
185
        {
186
            var containingNamespace = typeSymbol.ContainingNamespace.ToDisplayString();
2✔
187
            return containingNamespace == "System" && 
2!
188
                typeSymbol is INamedTypeSymbol namedType && 
2✔
189
                namedType.TypeArguments.Length == 1;
2✔
190
        }
191

192
        return false;
21✔
193
    }
194
}
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