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

SamboyCoding / Cpp2IL / 12320749043

13 Dec 2024 06:07PM UTC coverage: 27.79% (-0.3%) from 28.128%
12320749043

Pull #393

github

web-flow
Merge b9caa35d0 into ac99859af
Pull Request #393: Add Type field to AttributeAttribute

1268 of 6370 branches covered (19.91%)

Branch coverage included in aggregate %.

3 of 93 new or added lines in 7 files covered. (3.23%)

45 existing lines in 4 files now uncovered.

3386 of 10377 relevant lines covered (32.63%)

123656.67 hits per line

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

0.0
/Cpp2IL.Core/Utils/AttributeInjectionUtils.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Reflection;
5
using Cpp2IL.Core.Model;
6
using Cpp2IL.Core.Model.Contexts;
7
using Cpp2IL.Core.Model.CustomAttributes;
8
using LibCpp2IL.BinaryStructures;
9
using LibCpp2IL.Reflection;
10

11
namespace Cpp2IL.Core.Utils;
12

13
public static class AttributeInjectionUtils
14
{
15
    /// <summary>
16
    /// Inject an attribute with no fields nor properties into the <see cref="ApplicationAnalysisContext"/>.
17
    /// </summary>
18
    /// <returns>A dictionary of assembly contexts to their inject attribute constructors.</returns>
19
    public static Dictionary<AssemblyAnalysisContext, InjectedMethodAnalysisContext> InjectZeroParameterAttribute(ApplicationAnalysisContext appContext, string ns, string name, AttributeTargets attributeTargets, bool allowMultiple)
20
    {
21
        var multiInjectType = appContext.InjectTypeIntoAllAssemblies(ns, name, appContext.SystemTypes.SystemAttributeType);
×
22
        ApplyAttributeUsageAttribute(appContext, multiInjectType, attributeTargets, allowMultiple);
×
23
        return multiInjectType.InjectConstructor(false);
×
24
    }
25

26
    public static Dictionary<AssemblyAnalysisContext, (InjectedMethodAnalysisContext, InjectedFieldAnalysisContext)> InjectOneParameterAttribute(ApplicationAnalysisContext appContext, string ns, string name, AttributeTargets attributeTargets, bool allowMultiple, TypeAnalysisContext fieldType, string fieldName)
27
    {
28
        var multiInjectType = appContext.InjectTypeIntoAllAssemblies(ns, name, appContext.SystemTypes.SystemAttributeType);
×
29
        ApplyAttributeUsageAttribute(appContext, multiInjectType, attributeTargets, allowMultiple);
×
30

31
        var fields = multiInjectType.InjectFieldToAllAssemblies(fieldName, fieldType, FieldAttributes.Public);
×
32

33
        var constructors = multiInjectType.InjectConstructor(false);
×
34

35
        return multiInjectType.InjectedTypes.ToDictionary(t => t.DeclaringAssembly, t => (constructors[t.DeclaringAssembly], fields[t.DeclaringAssembly]));
×
36
    }
37

38
    public static Dictionary<AssemblyAnalysisContext, (InjectedMethodAnalysisContext, InjectedFieldAnalysisContext, InjectedFieldAnalysisContext)> InjectTwoParameterAttribute(ApplicationAnalysisContext appContext, string ns, string name, AttributeTargets attributeTargets, bool allowMultiple, TypeAnalysisContext fieldType1, string fieldName1, TypeAnalysisContext fieldType2, string fieldName2)
39
    {
40
        var multiInjectType = appContext.InjectTypeIntoAllAssemblies(ns, name, appContext.SystemTypes.SystemAttributeType);
×
41
        ApplyAttributeUsageAttribute(appContext, multiInjectType, attributeTargets, allowMultiple);
×
42

43
        var firstFields = multiInjectType.InjectFieldToAllAssemblies(fieldName1, fieldType1, FieldAttributes.Public);
×
44

45
        var secondFields = multiInjectType.InjectFieldToAllAssemblies(fieldName2, fieldType2, FieldAttributes.Public);
×
46

47
        var constructors = multiInjectType.InjectConstructor(false);
×
48

49
        return multiInjectType.InjectedTypes.ToDictionary(t => t.DeclaringAssembly, t =>
×
50
        {
×
51
            return (constructors[t.DeclaringAssembly], firstFields[t.DeclaringAssembly], secondFields[t.DeclaringAssembly]);
×
52
        });
×
53
    }
54

55
    public static Dictionary<AssemblyAnalysisContext, (InjectedMethodAnalysisContext, InjectedFieldAnalysisContext, InjectedFieldAnalysisContext, InjectedFieldAnalysisContext)> InjectThreeParameterAttribute(ApplicationAnalysisContext appContext, string ns, string name, AttributeTargets attributeTargets, bool allowMultiple, TypeAnalysisContext fieldType1, string fieldName1, TypeAnalysisContext fieldType2, string fieldName2, TypeAnalysisContext fieldType3, string fieldName3)
56
    {
57
        var multiInjectType = appContext.InjectTypeIntoAllAssemblies(ns, name, appContext.SystemTypes.SystemAttributeType);
×
58
        ApplyAttributeUsageAttribute(appContext, multiInjectType, attributeTargets, allowMultiple);
×
59

60
        var firstFields = multiInjectType.InjectFieldToAllAssemblies(fieldName1, fieldType1, FieldAttributes.Public);
×
61

62
        var secondFields = multiInjectType.InjectFieldToAllAssemblies(fieldName2, fieldType2, FieldAttributes.Public);
×
63

64
        var thirdFields = multiInjectType.InjectFieldToAllAssemblies(fieldName3, fieldType3, FieldAttributes.Public);
×
65

66
        var constructors = multiInjectType.InjectConstructor(false);
×
67

68
        return multiInjectType.InjectedTypes.ToDictionary(t => t.DeclaringAssembly, t =>
×
69
        {
×
70
            return (constructors[t.DeclaringAssembly], firstFields[t.DeclaringAssembly], secondFields[t.DeclaringAssembly], thirdFields[t.DeclaringAssembly]);
×
71
        });
×
72
    }
73

74
    public static Dictionary<AssemblyAnalysisContext, (InjectedMethodAnalysisContext, InjectedFieldAnalysisContext[])> InjectAttribute(ApplicationAnalysisContext appContext, string ns, string name, AttributeTargets attributeTargets, bool allowMultiple, params (TypeAnalysisContext, string)[] fields)
75
    {
76
        var multiInjectType = appContext.InjectTypeIntoAllAssemblies(ns, name, appContext.SystemTypes.SystemAttributeType);
×
77
        ApplyAttributeUsageAttribute(appContext, multiInjectType, attributeTargets, allowMultiple);
×
78

79
        var injectedFields = new Dictionary<AssemblyAnalysisContext, InjectedFieldAnalysisContext>[fields.Length];
×
80
        for (var i = 0; i < fields.Length; i++)
×
81
        {
82
            injectedFields[i] = multiInjectType.InjectFieldToAllAssemblies(fields[i].Item2, fields[i].Item1, FieldAttributes.Public);
×
83
        }
84

85
        var constructors = multiInjectType.InjectConstructor(false);
×
86

87
        return multiInjectType.InjectedTypes.ToDictionary(t => t.DeclaringAssembly, t =>
×
88
        {
×
89
            return (constructors[t.DeclaringAssembly], injectedFields.Select(d => d[t.DeclaringAssembly]).ToArray());
×
90
        });
×
91
    }
92

93
    private static void ApplyAttributeUsageAttribute(ApplicationAnalysisContext appContext, MultiAssemblyInjectedType multiAssemblyInjectedType, AttributeTargets attributeTargets, bool allowMultiple)
94
    {
95
        var mscorlibAssembly = appContext.GetAssemblyByName("mscorlib") ?? throw new("Could not find mscorlib");
×
96
        var targetsEnumType = GetAttributeTargetsType(mscorlibAssembly);
×
97
        var usageAttribute = mscorlibAssembly.GetTypeByFullName($"System.{nameof(AttributeUsageAttribute)}") ?? throw new("Could not find AttributeUsageAttribute");
×
98
        var usageConstructor = usageAttribute.Methods.First(m => (m.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public && m.Name == ".ctor");
×
99
        var allowMultipleProperty = usageAttribute.Properties.First(p => p.Name == nameof(AttributeUsageAttribute.AllowMultiple));
×
100
        foreach (var injectedType in multiAssemblyInjectedType.InjectedTypes)
×
101
        {
102
            var newAttribute = new AnalyzedCustomAttribute(usageConstructor);
×
103
            var enumParameter = new CustomAttributeEnumParameter(targetsEnumType, appContext, newAttribute, CustomAttributeParameterKind.ConstructorParam, 0);
×
104
            enumParameter.UnderlyingPrimitiveParameter.PrimitiveValue = (int)attributeTargets;
×
105
            newAttribute.ConstructorParameters.Add(enumParameter);
×
106
            newAttribute.Properties.Add(new(allowMultipleProperty, new CustomAttributePrimitiveParameter(allowMultiple, newAttribute, CustomAttributeParameterKind.Property, 1)));
×
107
            injectedType.AnalyzeCustomAttributeData();
×
108
            injectedType.CustomAttributes!.Add(newAttribute); //Nullability checked above
×
109
        }
110
    }
×
111

112
    public static void AddZeroParameterAttribute(HasCustomAttributes customAttributeHolder, MethodAnalysisContext constructor)
113
    {
114
        var newAttribute = new AnalyzedCustomAttribute(constructor);
×
115
        customAttributeHolder.CustomAttributes!.Add(newAttribute); //Nullability checked elsewhere
×
116
    }
×
117

118
    public static void AddOneParameterAttribute(HasCustomAttributes customAttributeHolder, (MethodAnalysisContext, FieldAnalysisContext) attributeInfo, object fieldValue)
119
    {
120
        AddOneParameterAttribute(customAttributeHolder, attributeInfo.Item1, attributeInfo.Item2, fieldValue);
×
121
    }
×
122

123
    public static void AddOneParameterAttribute(HasCustomAttributes customAttributeHolder, MethodAnalysisContext constructor, FieldAnalysisContext field, object fieldValue)
124
    {
125
        var newAttribute = new AnalyzedCustomAttribute(constructor);
×
126
        newAttribute.Fields.Add(new(field, MakeFieldParameter(fieldValue, newAttribute, 0)));
×
127
        customAttributeHolder.CustomAttributes!.Add(newAttribute); //Nullability checked elsewhere
×
128
    }
×
129

130
    public static void AddTwoParameterAttribute(HasCustomAttributes customAttributeHolder, (MethodAnalysisContext, FieldAnalysisContext, FieldAnalysisContext) attributeInfo, object fieldValue1, object fieldValue2)
131
    {
132
        AddTwoParameterAttribute(customAttributeHolder, attributeInfo.Item1, attributeInfo.Item2, fieldValue1, attributeInfo.Item3, fieldValue2);
×
133
    }
×
134

135
    public static void AddTwoParameterAttribute(HasCustomAttributes customAttributeHolder, MethodAnalysisContext constructor, FieldAnalysisContext field1, object fieldValue1, FieldAnalysisContext field2, object fieldValue2)
136
    {
137
        var newAttribute = new AnalyzedCustomAttribute(constructor);
×
138
        newAttribute.Fields.Add(new(field1, MakeFieldParameter(fieldValue1, newAttribute, 0)));
×
139
        newAttribute.Fields.Add(new(field2, MakeFieldParameter(fieldValue2, newAttribute, 1)));
×
140
        customAttributeHolder.CustomAttributes!.Add(newAttribute); //Nullability checked elsewhere
×
141
    }
×
142

143
    public static void AddAttribute(HasCustomAttributes customAttributeHolder, MethodAnalysisContext constructor, params (FieldAnalysisContext, object)[] fields)
144
    {
145
        AddAttribute(customAttributeHolder, constructor, fields.AsEnumerable());
×
146
    }
×
147

148
    public static void AddAttribute(HasCustomAttributes customAttributeHolder, MethodAnalysisContext constructor, IEnumerable<(FieldAnalysisContext, object)> fields)
149
    {
150
        var newAttribute = new AnalyzedCustomAttribute(constructor);
×
151
        var i = 0;
×
152
        foreach (var field in fields)
×
153
        {
154
            newAttribute.Fields.Add(new(field.Item1, MakeFieldParameter(field.Item2, newAttribute, i)));
×
155
            i++;
×
156
        }
157

158
        customAttributeHolder.CustomAttributes!.Add(newAttribute); //Nullability checked elsewhere
×
159
    }
×
160

161
    private static Il2CppType GetAttributeTargetsType(AssemblyAnalysisContext mscorlibAssembly)
162
    {
163
        var targetsEnum = mscorlibAssembly.GetTypeByFullName($"System.{nameof(AttributeTargets)}") ?? throw new("Could not find AttributeTargets");
×
164
        if (targetsEnum.Definition == null)
×
165
        {
166
            throw new NullReferenceException("AttributeTargets had a null Definition");
×
167
        }
168
        else
169
        {
170
            return LibCpp2IlReflection.GetTypeFromDefinition(targetsEnum.Definition) ?? throw new("Could not get the Il2CppType for AttributeTargets");
×
171
        }
172
    }
173

174
    private static BaseCustomAttributeParameter MakeFieldParameter(object fieldValue, AnalyzedCustomAttribute owner, int index)
175
    {
176
        return MakeCustomAttributeParameter(fieldValue, owner, index, CustomAttributeParameterKind.Field);
×
177
    }
178

179
    private static BaseCustomAttributeParameter MakeCustomAttributeParameter(object? value, AnalyzedCustomAttribute owner, int index, CustomAttributeParameterKind parameterKind)
180
    {
181
        return value switch
×
182
        {
×
183
            Il2CppType type => new CustomAttributeTypeParameter(type, owner, parameterKind, index),
×
NEW
184
            TypeAnalysisContext type => new CustomAttributeTypeParameter(type, owner, parameterKind, index),
×
NEW
185
            TypeAnalysisContext?[] types => new CustomAttributeArrayParameter(owner, parameterKind, index) { ArrType = Il2CppTypeEnum.IL2CPP_TYPE_IL2CPP_TYPE_INDEX, ArrayElements = types.Select(t => (BaseCustomAttributeParameter)new CustomAttributeTypeParameter(t, owner, CustomAttributeParameterKind.ArrayElement, index)).ToList() },
×
186
            object?[] objects => new CustomAttributeArrayParameter(owner, parameterKind, index)
×
187
            {
×
188
                ArrType = Il2CppTypeEnum.IL2CPP_TYPE_OBJECT,
×
189
                ArrayElements = objects.Select(obj => obj is null
×
190
                    ? new CustomAttributeNullParameter(owner, CustomAttributeParameterKind.ArrayElement, index)
×
191
                    : MakeCustomAttributeParameter(obj, owner, index, CustomAttributeParameterKind.ArrayElement)).ToList()
×
192
            },
×
193
            IConvertible convertible => new CustomAttributePrimitiveParameter(convertible, owner, parameterKind, index),
×
194
            null => new CustomAttributeNullParameter(owner, parameterKind, index),
×
195
            _ => throw new NotSupportedException(),
×
196
        };
×
197
    }
198
}
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