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

SamboyCoding / Cpp2IL / 13494977167

24 Feb 2025 09:38AM UTC coverage: 27.383% (+0.04%) from 27.341%
13494977167

Pull #414

github

web-flow
Merge 2fd947674 into 16c3a7581
Pull Request #414: Fix explicit interface method overrides

1261 of 6406 branches covered (19.68%)

Branch coverage included in aggregate %.

17 of 87 new or added lines in 10 files covered. (19.54%)

1 existing line in 1 file now uncovered.

3375 of 10524 relevant lines covered (32.07%)

123786.14 hits per line

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

26.96
/Cpp2IL.Core/Model/Contexts/TypeAnalysisContext.cs
1
using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Linq;
5
using System.Reflection;
6
using System.Text;
7
using Cpp2IL.Core.Api;
8
using Cpp2IL.Core.Utils;
9
using LibCpp2IL.BinaryStructures;
10
using LibCpp2IL.Metadata;
11
using LibCpp2IL.Reflection;
12
using StableNameDotNet.Providers;
13

14
namespace Cpp2IL.Core.Model.Contexts;
15

16
/// <summary>
17
/// Represents one managed type in the application.
18
/// </summary>
19
public class TypeAnalysisContext : HasCustomAttributesAndName, ITypeInfoProvider, ICSharpSourceToken
20
{
21
    internal const TypeAttributes DefaultTypeAttributes = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed;
22

23
    /// <summary>
24
    /// The context for the assembly this type was defined in.
25
    /// </summary>
26
    public readonly AssemblyAnalysisContext DeclaringAssembly;
27

28
    /// <summary>
29
    /// The underlying metadata for this type. Allows access to RGCTX data, the raw bitfield properties, interfaces, etc.
30
    /// </summary>
31
    public readonly Il2CppTypeDefinition? Definition;
32

33
    /// <summary>
34
    /// The analysis contexts for methods contained within this type.
35
    /// </summary>
36
    public readonly List<MethodAnalysisContext> Methods;
37

38
    /// <summary>
39
    /// The analysis contexts for properties contained within this type.
40
    /// </summary>
41
    public readonly List<PropertyAnalysisContext> Properties;
42

43
    /// <summary>
44
    /// The analysis contexts for events contained within this type.
45
    /// </summary>
46
    public readonly List<EventAnalysisContext> Events;
47

48
    /// <summary>
49
    /// The analysis contexts for fields contained within this type.
50
    /// </summary>
51
    public readonly List<FieldAnalysisContext> Fields;
52

53
    /// <summary>
54
    /// The analysis contexts for nested types within this type.
55
    /// </summary>
56
    public List<TypeAnalysisContext> NestedTypes { get; internal set; } = [];
527,094✔
57

58
    protected override int CustomAttributeIndex => Definition!.CustomAttributeIndex;
29,260✔
59

60
    public override AssemblyAnalysisContext CustomAttributeAssembly => DeclaringAssembly;
58,876✔
61

62
    public override string DefaultName => Definition?.Name! ?? throw new("Subclasses of TypeAnalysisContext must override DefaultName");
1,121!
63

64
    public virtual string DefaultNs => Definition?.Namespace ?? throw new("Subclasses of TypeAnalysisContext must override DefaultNs");
1,853!
65

66
    public string? OverrideNs { get; set; }
1,861✔
67

68
    public string Namespace => OverrideNs ?? DefaultNs;
1,861✔
69

70
    public TypeAnalysisContext? OverrideBaseType { get; protected set; }
338,134✔
71

72
    public TypeAnalysisContext? DeclaringType { get; protected internal set; }
11,138✔
73

74
    public TypeAnalysisContext? EnumUnderlyingType => Definition == null ? null : DeclaringAssembly.ResolveIl2CppType(Definition.EnumUnderlyingType);
×
75

76
    public TypeAnalysisContext? BaseType => OverrideBaseType ?? (Definition == null ? null : DeclaringAssembly.ResolveIl2CppType(Definition.RawBaseType));
168,974!
77

78
    public TypeAnalysisContext[] InterfaceContexts => (Definition?.RawInterfaces.Select(DeclaringAssembly.ResolveIl2CppType).ToArray() ?? [])!;
×
79
    
80
    public bool IsPrimitive
81
    {
82
        get
83
        {
84
            if (Definition == null)
×
85
                return false;
×
86

87
            if (Definition.RawBaseType?.Type.IsIl2CppPrimitive() == true)
×
88
                return true;
×
89
            
90
            //Might still be TYPE_CLASS but yet int or something, so check it directly
91
            return AppContext.SystemTypes.IsPrimitive(this);
×
92
        }
93
    }
94

95
    public virtual Il2CppTypeEnum Type
96
    {
97
        get
98
        {
99
            if (Definition is { RawBaseType: not null })
×
100
                return Definition.RawBaseType.Type;
×
101

102
            if (AppContext.SystemTypes.TryGetIl2CppTypeEnum(this, out var value))
×
103
                return value;
×
104

105
            if (IsEnumType)
×
106
                return Il2CppTypeEnum.IL2CPP_TYPE_ENUM;
×
107

108
            if (IsValueType)
×
109
                return Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE;
×
110

111
            return Il2CppTypeEnum.IL2CPP_TYPE_CLASS;
×
112
        }
113
    }
114

115
    public string FullName
116
    {
117
        get
118
        {
119
            if (DeclaringType != null)
1,125✔
120
                return DeclaringType.FullName + "." + Name;
188✔
121

122
            if (string.IsNullOrEmpty(Namespace))
937✔
123
                return Name;
13✔
124

125
            return $"{Namespace}.{Name}";
924✔
126
        }
127
    }
128

129
    /// <summary>
130
    /// Returns the namespace of this type expressed as a folder hierarchy, with each sub-namespace becoming a sub-directory.
131
    /// If this type is in the global namespace, this will return an empty string.
132
    /// </summary>
133
    public string NamespaceAsSubdirs
134
    {
135
        get
136
        {
137
            var ns = Namespace;
×
138
            return string.IsNullOrEmpty(ns) ? "" : Path.Combine(MiscUtils.CleanPathElement(ns).Split('.'));
×
139
        }
140
    }
141

142
    /// <summary>
143
    /// Returns the top-level type this type is nested inside. If this type is not nested, will return this type.
144
    /// </summary>
145
    public TypeAnalysisContext UltimateDeclaringType => DeclaringType ?? this;
×
146

147
    public TypeAnalysisContext(Il2CppTypeDefinition? il2CppTypeDefinition, AssemblyAnalysisContext containingAssembly) : base(il2CppTypeDefinition?.Token ?? 0, containingAssembly.AppContext)
523,350✔
148
    {
149
        DeclaringAssembly = containingAssembly;
523,350✔
150
        Definition = il2CppTypeDefinition;
523,350✔
151

152
        if (Definition != null)
523,350✔
153
        {
154
            InitCustomAttributeData();
44,068✔
155

156
            Methods = Definition.Methods!.Select(m => new MethodAnalysisContext(m, this)).ToList();
292,582✔
157
            Properties = Definition.Properties!.Select(p => new PropertyAnalysisContext(p, this)).ToList();
86,248✔
158
            Events = Definition.Events!.Select(e => new EventAnalysisContext(e, this)).ToList();
44,248✔
159
            Fields = Definition.FieldInfos!.ToList().Select(f => new FieldAnalysisContext(f, this)).ToList();
214,820✔
160
        }
161
        else
162
        {
163
            Methods = [];
479,282✔
164
            Properties = [];
479,282✔
165
            Events = [];
479,282✔
166
            Fields = [];
479,282✔
167
        }
168
    }
479,282✔
169

170
    public MethodAnalysisContext? GetMethod(Il2CppMethodDefinition? methodDefinition)
171
    {
172
        if (methodDefinition == null)
230,298✔
173
            return null;
33,012✔
174

175
        return Methods.Find(m => m.Definition == methodDefinition);
3,733,456✔
176
    }
177

178
    public List<MethodAnalysisContext> GetConstructors() => Methods.Where(m => m.Definition!.Name == ".ctor").ToList();
×
179

180
    public override string ToString() => $"Type: {Definition?.FullName}";
×
181

182
    public virtual string GetCSharpSourceString()
183
    {
184
        if (Definition != null)
×
185
            return Definition.FullName!;
×
186

187
        var ret = new StringBuilder();
×
188
        if (OverrideNs != null)
×
189
            ret.Append(OverrideNs).Append('.');
×
190

191
        ret.Append(Name);
×
192

193
        return ret.ToString();
×
194
    }
195

196
    public ArrayTypeAnalysisContext MakeArrayType(int rank)
197
    {
198
        return new(this, rank, DeclaringAssembly);
×
199
    }
200

201
    public ByRefTypeAnalysisContext MakeByReferenceType()
202
    {
203
        return new(this, DeclaringAssembly);
11,286✔
204
    }
205

206
    public GenericInstanceTypeAnalysisContext MakeGenericInstanceType(IEnumerable<TypeAnalysisContext> genericArguments)
207
    {
NEW
208
        return new(this, genericArguments, DeclaringAssembly);
×
209
    }
210

211
    public PointerTypeAnalysisContext MakePointerType()
212
    {
213
        return new(this, DeclaringAssembly);
×
214
    }
215

216
    public SzArrayTypeAnalysisContext MakeSzArrayType()
217
    {
218
        return new(this, DeclaringAssembly);
×
219
    }
220

221
    #region StableNameDotNet implementation
222

223
    public IEnumerable<ITypeInfoProvider> GetBaseTypeHierarchy()
224
    {
225
        if (OverrideBaseType != null)
×
226
            throw new("Type hierarchy for injected types is not supported");
×
227

228
        var baseType = Definition!.RawBaseType;
×
229
        while (baseType != null)
×
230
        {
231
            yield return GetSndnProviderForType(AppContext, baseType);
×
232

233
            baseType = baseType.CoerceToUnderlyingTypeDefinition().RawBaseType;
×
234
        }
235
    }
×
236

237
    public static ITypeInfoProvider GetSndnProviderForType(ApplicationAnalysisContext appContext, Il2CppType type)
238
    {
239
        if (type.Type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)
×
240
        {
241
            var genericClass = type.GetGenericClass();
×
242
            var elementType = appContext.ResolveContextForType(genericClass.TypeDefinition)!;
×
243

244
            var genericParamTypes = genericClass.Context.ClassInst.Types;
×
245

246
            if (genericParamTypes.Any(t => t.Type is Il2CppTypeEnum.IL2CPP_TYPE_VAR or Il2CppTypeEnum.IL2CPP_TYPE_MVAR))
×
247
                //Discard non-fixed generic instances
248
                return elementType;
×
249

250
            var genericArguments = genericParamTypes.Select(t => GetSndnProviderForType(appContext, t)).ToArray();
×
251

252
            return new GenericInstanceTypeInfoProviderWrapper(elementType, genericArguments);
×
253
        }
254

255
        if (type.Type is Il2CppTypeEnum.IL2CPP_TYPE_VAR or Il2CppTypeEnum.IL2CPP_TYPE_MVAR)
×
256
            return new GenericParameterTypeInfoProviderWrapper(type.GetGenericParameterDef().Name!);
×
257

258
        if (type.Type is Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY or Il2CppTypeEnum.IL2CPP_TYPE_PTR)
×
259
            return GetSndnProviderForType(appContext, type.GetEncapsulatedType());
×
260

261
        if (type.Type is Il2CppTypeEnum.IL2CPP_TYPE_ARRAY)
×
262
            return GetSndnProviderForType(appContext, type.GetArrayElementType());
×
263

264
        if (type.Type.IsIl2CppPrimitive())
×
265
            return appContext.ResolveContextForType(LibCpp2IlReflection.PrimitiveTypeDefinitions[type.Type])!;
×
266

267
        return appContext.ResolveContextForType(type.AsClass())!;
×
268
    }
269

270
    public IEnumerable<ITypeInfoProvider> Interfaces => Definition!.RawInterfaces!.Select(t => GetSndnProviderForType(AppContext, t));
×
271
    public virtual TypeAttributes TypeAttributes => Definition?.Attributes ?? DefaultTypeAttributes;
7!
272
    public virtual int GenericParameterCount => Definition!.GenericContainer?.genericParameterCount ?? 0;
×
273
    public string OriginalTypeName => DefaultName;
×
274
    public string RewrittenTypeName => Name;
×
275
    public string TypeNamespace => Namespace;
×
276
    public virtual bool IsGenericInstance => false;
×
277
    public virtual bool IsValueType => Definition?.IsValueType ?? BaseType is { Namespace: "System", Name: "ValueType" };
×
278
    public bool IsEnumType => Definition?.IsEnumType ?? BaseType is { Namespace: "System", Name: "Enum" };
×
279
    public bool IsInterface => Definition?.IsInterface ?? ((TypeAttributes & TypeAttributes.Interface) != default);
11!
280
    public IEnumerable<ITypeInfoProvider> GenericArgumentInfoProviders => Array.Empty<ITypeInfoProvider>();
×
281
    public IEnumerable<IFieldInfoProvider> FieldInfoProviders => Fields;
×
282
    public IEnumerable<IMethodInfoProvider> MethodInfoProviders => Methods;
×
283
    public IEnumerable<IPropertyInfoProvider> PropertyInfoProviders => Properties;
×
284
    public ITypeInfoProvider? DeclaringTypeInfoProvider => DeclaringType;
×
285

286
    #endregion
287
}
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