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

SamboyCoding / Cpp2IL / 20487925661

24 Dec 2025 02:11PM UTC coverage: 34.275% (-0.04%) from 34.31%
20487925661

push

github

SamboyCoding
Other properties too

This also makes ParameterAnalysisContext::ParameterType not virtual

1791 of 6588 branches covered (27.19%)

Branch coverage included in aggregate %.

10 of 20 new or added lines in 7 files covered. (50.0%)

129 existing lines in 7 files now uncovered.

4191 of 10865 relevant lines covered (38.57%)

180313.71 hits per line

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

35.83
/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 : HasGenericParameters, ITypeInfoProvider, ICSharpSourceToken
20
{
21
    /// <summary>
22
    /// The context for the assembly this type was defined in.
23
    /// </summary>
24
    public readonly AssemblyAnalysisContext DeclaringAssembly;
25

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

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

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

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

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

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

56
    protected override int CustomAttributeIndex => Definition!.CustomAttributeIndex;
61,446✔
57

58
    public override AssemblyAnalysisContext CustomAttributeAssembly => DeclaringAssembly;
173,210✔
59

60
    public override string DefaultName => Definition?.Name! ?? throw new("Subclasses of TypeAnalysisContext must override DefaultName");
232,714!
61

62
    public virtual string DefaultNamespace => Definition?.Namespace ?? throw new("Subclasses of TypeAnalysisContext must override DefaultNs");
230,424!
63

64
    public string? OverrideNamespace { get; set; }
231,195✔
65

66
    public string Namespace
67
    {
68
        get => OverrideNamespace ?? DefaultNamespace;
231,195✔
NEW
69
        set => OverrideNamespace = value;
×
70
    }
71

72
    public virtual TypeAttributes DefaultAttributes => Definition?.Attributes ?? TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed;
17,593!
73

74
    public virtual TypeAttributes? OverrideAttributes { get; set; }
17,593✔
75

76
    public TypeAttributes Attributes
77
    {
78
        get => OverrideAttributes ?? DefaultAttributes;
17,593!
UNCOV
79
        set => OverrideAttributes = value;
×
80
    }
81

82
    public virtual TypeAnalysisContext? DefaultBaseType => Definition == null ? null : DeclaringAssembly.ResolveIl2CppType(Definition.RawBaseType);
445,058!
83

84
    public TypeAnalysisContext? OverrideBaseType { get; set; }
445,124✔
85

86
    public TypeAnalysisContext? BaseType
87
    {
88
        get => OverrideBaseType ?? DefaultBaseType;
445,124✔
NEW
89
        set => OverrideBaseType = value;
×
90
    }
91

92
    public TypeAnalysisContext? DeclaringType { get; protected internal set; }
737,312✔
93

UNCOV
94
    public TypeAnalysisContext? EnumUnderlyingType => Definition == null ? null : DeclaringAssembly.ResolveIl2CppType(Definition.EnumUnderlyingType);
×
95

96
    private List<TypeAnalysisContext>? _interfaceContexts;
97
    public List<TypeAnalysisContext> InterfaceContexts
98
    {
99
        get
100
        {
101
            // Lazy load the interface contexts
102
            _interfaceContexts ??= (Definition?.RawInterfaces.Select(DeclaringAssembly.ResolveIl2CppType).ToList() ?? [])!;
14,420!
103
            return _interfaceContexts;
14,420✔
104
        }
105
    }
106

107
    private List<GenericParameterTypeAnalysisContext>? _genericParameters;
108
    public override List<GenericParameterTypeAnalysisContext> GenericParameters
109
    {
110
        get
111
        {
112
            // Lazy load the generic parameters
113
            _genericParameters ??= Definition?.GenericContainer?.GenericParameters.Select(g => new GenericParameterTypeAnalysisContext(g, this)).ToList() ?? [];
324,346!
114
            return _genericParameters;
318,452✔
115
        }
116
    }
117

118
    public virtual Il2CppTypeEnum Type
119
    {
120
        get
121
        {
122
            if (AppContext.SystemTypes.TryGetIl2CppTypeEnum(this, out var value))
×
UNCOV
123
                return value;
×
124

125
            if (IsEnumType)
×
UNCOV
126
                return Il2CppTypeEnum.IL2CPP_TYPE_ENUM;
×
127

UNCOV
128
            if (IsValueType)
×
UNCOV
129
                return Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE;
×
130

UNCOV
131
            return Il2CppTypeEnum.IL2CPP_TYPE_CLASS;
×
132
        }
133
    }
134

135
    public string DefaultFullName
136
    {
137
        get
138
        {
139
            if (DeclaringType != null)
×
UNCOV
140
                return DeclaringType.DefaultFullName + "+" + DefaultName;
×
141

UNCOV
142
            if (string.IsNullOrEmpty(DefaultNamespace))
×
UNCOV
143
                return DefaultName;
×
144

UNCOV
145
            return $"{DefaultNamespace}.{DefaultName}";
×
146
        }
147
    }
148

149
    public string FullName
150
    {
151
        get
152
        {
153
            if (DeclaringType != null)
134,112✔
154
                return DeclaringType.FullName + "+" + Name;
24,761✔
155

156
            if (string.IsNullOrEmpty(Namespace))
109,351✔
157
                return Name;
1,928✔
158

159
            return $"{Namespace}.{Name}";
107,423✔
160
        }
161
    }
162

163
    public TypeAttributes Visibility
164
    {
165
        get
166
        {
167
            return Attributes & TypeAttributes.VisibilityMask;
7✔
168
        }
169
        set
170
        {
UNCOV
171
            Attributes = (Attributes & ~TypeAttributes.VisibilityMask) | (value & TypeAttributes.VisibilityMask);
×
172
        }
×
173
    }
174

175
    public bool IsInterface => (Attributes & TypeAttributes.Interface) != default;
3,166✔
UNCOV
176
    public bool IsAbstract => (Attributes & TypeAttributes.Abstract) != default;
×
UNCOV
177
    public bool IsSealed => (Attributes & TypeAttributes.Sealed) != default;
×
UNCOV
178
    public bool IsStatic => IsAbstract && IsSealed;
×
179

180
    /// <summary>
181
    /// Returns the namespace of this type expressed as a folder hierarchy, with each sub-namespace becoming a sub-directory.
182
    /// If this type is in the global namespace, this will return an empty string.
183
    /// </summary>
184
    public string NamespaceAsSubdirs
185
    {
186
        get
187
        {
UNCOV
188
            var ns = Namespace;
×
UNCOV
189
            return string.IsNullOrEmpty(ns) ? "" : Path.Combine(MiscUtils.CleanPathElement(ns).Split('.'));
×
190
        }
191
    }
192

193
    /// <summary>
194
    /// Returns the top-level type this type is nested inside. If this type is not nested, will return this type.
195
    /// </summary>
UNCOV
196
    public TypeAnalysisContext UltimateDeclaringType => DeclaringType ?? this;
×
197

198
    public TypeAnalysisContext(Il2CppTypeDefinition? il2CppTypeDefinition, AssemblyAnalysisContext containingAssembly) : base(il2CppTypeDefinition?.Token ?? 0, containingAssembly.AppContext)
616,036✔
199
    {
200
        DeclaringAssembly = containingAssembly;
616,036✔
201
        Definition = il2CppTypeDefinition;
616,036✔
202

203
        if (Definition != null)
616,036✔
204
        {
205
            InitCustomAttributeData();
76,254✔
206

207
            Methods = Definition.Methods!.Select(m => new MethodAnalysisContext(m, this)).ToList();
516,234✔
208
            Properties = Definition.Properties!.Select(p => new PropertyAnalysisContext(p, this)).ToList();
152,226✔
209
            Events = Definition.Events!.Select(e => new EventAnalysisContext(e, this)).ToList();
76,599✔
210
            Fields = Definition.FieldInfos!.ToList().Select(f => new FieldAnalysisContext(f, this)).ToList();
376,575✔
211
        }
212
        else
213
        {
214
            Methods = [];
539,782✔
215
            Properties = [];
539,782✔
216
            Events = [];
539,782✔
217
            Fields = [];
539,782✔
218
        }
219
    }
539,782✔
220

221
    public MethodAnalysisContext? GetMethod(Il2CppMethodDefinition? methodDefinition)
222
    {
223
        if (methodDefinition == null)
451,299✔
224
            return null;
57,795✔
225

226
        return Methods.Find(m => m.Definition == methodDefinition);
7,564,371✔
227
    }
228

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

231
    public override string ToString() => $"Type: {FullName}";
×
232

233
    public virtual string GetCSharpSourceString()
234
    {
235
        if (Definition != null)
×
236
            return Definition.FullName!;
×
237

238
        var ret = new StringBuilder();
×
UNCOV
239
        if (OverrideNamespace != null)
×
240
            ret.Append(OverrideNamespace).Append('.');
×
241

UNCOV
242
        ret.Append(Name);
×
243

UNCOV
244
        return ret.ToString();
×
245
    }
246

247
    public ArrayTypeAnalysisContext MakeArrayType(int rank)
248
    {
UNCOV
249
        return new(this, rank, DeclaringAssembly);
×
250
    }
251

252
    public ByRefTypeAnalysisContext MakeByReferenceType()
253
    {
254
        return new(this, DeclaringAssembly);
16,856✔
255
    }
256

257
    public GenericInstanceTypeAnalysisContext MakeGenericInstanceType(params IEnumerable<TypeAnalysisContext> genericArguments)
258
    {
259
        return new(this, genericArguments, DeclaringAssembly);
73,857✔
260
    }
261

262
    public PointerTypeAnalysisContext MakePointerType()
263
    {
UNCOV
264
        return new(this, DeclaringAssembly);
×
265
    }
266

267
    public SzArrayTypeAnalysisContext MakeSzArrayType()
268
    {
UNCOV
269
        return new(this, DeclaringAssembly);
×
270
    }
271

272
    public PinnedTypeAnalysisContext MakePinnedType()
273
    {
UNCOV
274
        return new(this, DeclaringAssembly);
×
275
    }
276

277
    public BoxedTypeAnalysisContext MakeBoxedType()
278
    {
UNCOV
279
        return new(this, DeclaringAssembly);
×
280
    }
281

282
    public CustomModifierTypeAnalysisContext MakeCustomModifierType(TypeAnalysisContext modifierType, bool required)
283
    {
UNCOV
284
        return new(this, modifierType, required, DeclaringAssembly);
×
285
    }
286

287
    public InjectedTypeAnalysisContext InjectNestedType(string name, TypeAnalysisContext? baseType, TypeAttributes typeAttributes = TypeAttributes.NestedPublic | TypeAttributes.Sealed)
288
    {
289
        if (this is ReferencedTypeAnalysisContext)
43!
UNCOV
290
            throw new InvalidOperationException("Cannot inject nested types into a non type definition");
×
291

292
        var ret = new InjectedTypeAnalysisContext(DeclaringAssembly, "", name, baseType, typeAttributes);
43✔
293
        ret.DeclaringType = this;
43✔
294
        NestedTypes.Add(ret);
43✔
295
        DeclaringAssembly.InjectType(ret);
43✔
296
        return ret;
43✔
297
    }
298

299
    #region StableNameDotNet implementation
300

301
    public IEnumerable<ITypeInfoProvider> GetBaseTypeHierarchy()
302
    {
303
        if (IsInjected)
×
UNCOV
304
            throw new("Type hierarchy for injected types is not supported");
×
305

UNCOV
306
        var baseType = Definition!.RawBaseType;
×
307
        while (baseType != null)
×
308
        {
309
            yield return GetSndnProviderForType(AppContext, baseType);
×
310

UNCOV
311
            baseType = baseType.CoerceToUnderlyingTypeDefinition().RawBaseType;
×
312
        }
313
    }
×
314

315
    public static ITypeInfoProvider GetSndnProviderForType(ApplicationAnalysisContext appContext, Il2CppType type)
316
    {
UNCOV
317
        if (type.Type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)
×
318
        {
UNCOV
319
            var genericClass = type.GetGenericClass();
×
320
            var elementType = appContext.ResolveContextForType(genericClass.TypeDefinition)!;
×
321

322
            var genericParamTypes = genericClass.Context.ClassInst.Types;
×
323

324
            if (genericParamTypes.Any(t => t.Type is Il2CppTypeEnum.IL2CPP_TYPE_VAR or Il2CppTypeEnum.IL2CPP_TYPE_MVAR))
×
325
                //Discard non-fixed generic instances
326
                return elementType;
×
327

UNCOV
328
            var genericArguments = genericParamTypes.Select(t => GetSndnProviderForType(appContext, t)).ToArray();
×
329

330
            return new GenericInstanceTypeInfoProviderWrapper(elementType, genericArguments);
×
331
        }
332

333
        if (type.Type is Il2CppTypeEnum.IL2CPP_TYPE_VAR or Il2CppTypeEnum.IL2CPP_TYPE_MVAR)
×
UNCOV
334
            return new GenericParameterTypeInfoProviderWrapper(type.GetGenericParameterDef().Name!);
×
335

336
        if (type.Type is Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY or Il2CppTypeEnum.IL2CPP_TYPE_PTR)
×
UNCOV
337
            return GetSndnProviderForType(appContext, type.GetEncapsulatedType());
×
338

339
        if (type.Type is Il2CppTypeEnum.IL2CPP_TYPE_ARRAY)
×
UNCOV
340
            return GetSndnProviderForType(appContext, type.GetArrayElementType());
×
341

UNCOV
342
        if (type.Type.IsIl2CppPrimitive())
×
UNCOV
343
            return appContext.ResolveContextForType(LibCpp2IlReflection.PrimitiveTypeDefinitions[type.Type])!;
×
344

345
        return appContext.ResolveContextForType(type.AsClass())!;
×
346
    }
347

348
    IEnumerable<ITypeInfoProvider> ITypeInfoProvider.Interfaces => Definition!.RawInterfaces!.Select(t => GetSndnProviderForType(AppContext, t));
×
349
    TypeAttributes ITypeInfoProvider.TypeAttributes => Attributes;
×
350
    int ITypeInfoProvider.GenericParameterCount => GenericParameters.Count;
×
UNCOV
351
    string ITypeInfoProvider.OriginalTypeName => DefaultName;
×
UNCOV
352
    string ITypeInfoProvider.RewrittenTypeName => Name;
×
UNCOV
353
    string ITypeInfoProvider.TypeNamespace => Namespace;
×
UNCOV
354
    public virtual bool IsGenericInstance => false;
×
355
    public virtual bool IsValueType
356
    {
357
        get
358
        {
359
            if (Definition is not null)
8,920!
360
                return Definition.IsValueType;
8,920✔
361

UNCOV
362
            if (BaseType is { Namespace: "System", Name: "ValueType" })
×
UNCOV
363
                return Namespace is not "System" || Name is not "Enum"; // Enum is a reference type
×
364

365
            return IsEnumType;
×
366
        }
367
    }
368

369
    public bool IsEnumType => Definition?.IsEnumType ?? BaseType is { Namespace: "System", Name: "Enum" };
×
370
    IEnumerable<ITypeInfoProvider> ITypeInfoProvider.GenericArgumentInfoProviders => [];
×
UNCOV
371
    IEnumerable<IFieldInfoProvider> ITypeInfoProvider.FieldInfoProviders => Fields;
×
UNCOV
372
    IEnumerable<IMethodInfoProvider> ITypeInfoProvider.MethodInfoProviders => Methods;
×
UNCOV
373
    IEnumerable<IPropertyInfoProvider> ITypeInfoProvider.PropertyInfoProviders => Properties;
×
UNCOV
374
    ITypeInfoProvider? ITypeInfoProvider.DeclaringTypeInfoProvider => DeclaringType;
×
375

376
    #endregion
377
}
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