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

SamboyCoding / Cpp2IL / 15618898121

12 Jun 2025 07:07PM UTC coverage: 34.334% (+0.03%) from 34.308%
15618898121

Pull #472

github

web-flow
Merge d25879329 into 9ce22e911
Pull Request #472: Handle self-referencing generic classes

1781 of 6564 branches covered (27.13%)

Branch coverage included in aggregate %.

8 of 14 new or added lines in 3 files covered. (57.14%)

6 existing lines in 2 files now uncovered.

4188 of 10821 relevant lines covered (38.7%)

181006.74 hits per line

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

64.29
/Cpp2IL.Core/Model/Contexts/GenericInstanceTypeAnalysisContext.cs
1
using System.Collections.Generic;
2
using System.Diagnostics;
3
using System.Linq;
4
using System.Reflection;
5
using System.Text;
6
using Cpp2IL.Core.Utils;
7
using LibCpp2IL.BinaryStructures;
8

9
namespace Cpp2IL.Core.Model.Contexts;
10

11
public class GenericInstanceTypeAnalysisContext : ReferencedTypeAnalysisContext
12
{
13
    public TypeAnalysisContext GenericType { get; }
545,865✔
14

15
    public List<TypeAnalysisContext> GenericArguments { get; } = [];
1,153,221✔
16

17
    public override TypeAttributes DefaultAttributes => GenericType.DefaultAttributes;
327✔
18

19
    public override TypeAttributes? OverrideAttributes { get => GenericType.OverrideAttributes; set => GenericType.OverrideAttributes = value; }
327✔
20

UNCOV
21
    public override string DefaultName => $"{GenericType.Name}<{string.Join(", ", GenericArguments.Select(a => a.Name))}>";
×
22

UNCOV
23
    public override string DefaultNamespace => GenericType.Namespace;
×
24

25
    public override TypeAnalysisContext? DefaultBaseType { get; }
65✔
26

UNCOV
27
    public sealed override Il2CppTypeEnum Type => Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST;
×
28

UNCOV
29
    public sealed override bool IsGenericInstance => true;
×
30

31
    public sealed override bool IsValueType => GenericType.IsValueType; //We don't set a definition so the default implementation cannot determine if we're a value type or not. 
8,920✔
32

33
    private GenericInstanceTypeAnalysisContext(Il2CppType rawType, AssemblyAnalysisContext referencedFrom) : base(referencedFrom)
11,313✔
34
    {
35
        // Cache this instance before resolving anything else, which might contain a reference to this instance.
36
        // https://github.com/SamboyCoding/Cpp2IL/issues/469
37
        referencedFrom.GenericInstanceTypesByIl2CppType.Add(rawType, this);
11,313✔
38

39
        //Generic type has to be a type definition
40
        var gClass = rawType.GetGenericClass();
11,313✔
41
        GenericType = AppContext.ResolveContextForType(gClass.TypeDefinition) ?? throw new($"Could not resolve type {gClass.TypeDefinition.FullName} for generic instance base type");
11,313!
42

43
        GenericArguments.AddRange(gClass.Context.ClassInst.Types.Select(referencedFrom.ResolveIl2CppType)!);
11,313✔
44

45
        SetDeclaringType();
11,313✔
46
    }
11,313✔
47

48
    public GenericInstanceTypeAnalysisContext(TypeAnalysisContext genericType, IEnumerable<TypeAnalysisContext> genericArguments, AssemblyAnalysisContext referencedFrom) : base(referencedFrom)
422,826✔
49
    {
50
        GenericType = genericType;
422,826✔
51
        GenericArguments.AddRange(genericArguments);
422,826✔
52
        DefaultBaseType = genericType.BaseType;
422,826✔
53

54
        SetDeclaringType();
422,826✔
55
    }
422,826✔
56

57
    public static GenericInstanceTypeAnalysisContext GetOrCreate(Il2CppType rawType, AssemblyAnalysisContext referencedFrom)
58
    {
59
        if (!referencedFrom.GenericInstanceTypesByIl2CppType.TryGetValue(rawType, out var result))
108,983✔
60
        {
61
            result = new GenericInstanceTypeAnalysisContext(rawType, referencedFrom);
11,313✔
62
            Debug.Assert(referencedFrom.GenericInstanceTypesByIl2CppType.ContainsKey(rawType), $"The {nameof(GenericInstanceTypeAnalysisContext)} constructor should add itself to the dictionary.");
63
        }
64

65
        return result;
108,983✔
66
    }
67

68
    public override string GetCSharpSourceString()
69
    {
NEW
70
        var sb = new StringBuilder();
×
71

NEW
72
        sb.Append(GenericType.GetCSharpSourceString());
×
NEW
73
        sb.Append('<');
×
NEW
74
        var first = true;
×
NEW
75
        foreach (var genericArgument in GenericArguments)
×
76
        {
NEW
77
            if (!first)
×
UNCOV
78
                sb.Append(", ");
×
79
            else
80
                first = false;
×
81

82
            sb.Append(genericArgument.GetCSharpSourceString());
×
83
        }
84

85
        sb.Append('>');
×
86

87
        return sb.ToString();
×
88
    }
89

90
    private void SetDeclaringType()
91
    {
92
        var declaringType = GenericType.DeclaringType;
434,139✔
93
        if (declaringType is null)
434,139✔
94
            return;
321,312✔
95

96
        DeclaringType = declaringType.GenericParameters.Count == 0
112,827✔
97
            ? declaringType
112,827✔
98
            : declaringType.MakeGenericInstanceType(GenericArguments.Take(declaringType.GenericParameters.Count));
112,827✔
99
    }
112,827✔
100
}
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