Skip to content

Commit b7b23e0

Browse files
committed
Generate Events
* Also clean up code surrounding strings Formatting
1 parent aa36797 commit b7b23e0

9 files changed

+137
-48
lines changed

Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs

+8-6
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ private string UnmangleFieldNameBase(FieldDefinition field, GeneratorOptions opt
4444

4545
if (!field.Name.IsObfuscated(options))
4646
{
47-
if (!field.Name.IsInvalidInSource())
48-
return field.Name!;
49-
return field.Name.FilterInvalidInSourceChars();
47+
return field.Name.MakeValidInSource();
5048
}
5149

5250
Debug.Assert(field.Signature is not null);
@@ -64,9 +62,13 @@ private string UnmangleFieldName(FieldDefinition field, GeneratorOptions options
6462

6563
if (!field.Name.IsObfuscated(options))
6664
{
67-
if (!field.Name.IsInvalidInSource())
68-
return field.Name!;
69-
return field.Name.FilterInvalidInSourceChars();
65+
var name = field.Name.MakeValidInSource();
66+
while (field.DeclaringType!.Events.Any(e => e.Name == name)
67+
|| field.DeclaringType!.Fields.Any(f => f.Name == name && f != field))
68+
{
69+
name += "_"; // Backing fields for events have the same name as the event.
70+
}
71+
return name;
7072
}
7173

7274
if (renamedFieldCounts == null) throw new ArgumentNullException(nameof(renamedFieldCounts));

Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs

+10-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Diagnostics;
22
using System.Runtime.CompilerServices;
33
using System.Text;
4+
using AsmResolver;
45
using AsmResolver.DotNet;
56
using AsmResolver.DotNet.Signatures;
67
using AsmResolver.PE.DotNet.Metadata.Tables;
@@ -73,12 +74,9 @@ public MethodRewriteContext(TypeRewriteContext declaringType, MethodDefinition o
7374

7475
foreach (var oldParameter in genericParams)
7576
{
76-
var genericParameter = new GenericParameter(oldParameter.Name);
77-
genericParameter.Attributes = oldParameter.Attributes.StripValueTypeConstraint();
78-
newMethod.GenericParameters.Add(genericParameter);
79-
80-
if (genericParameter.Name.IsInvalidInSource())
81-
genericParameter.Name = genericParameter.Name.FilterInvalidInSourceChars();
77+
newMethod.GenericParameters.Add(new GenericParameter(
78+
oldParameter.Name.MakeValidInSource(),
79+
oldParameter.Attributes.StripValueTypeConstraint()));
8280
}
8381
}
8482

@@ -94,7 +92,7 @@ public MethodRewriteContext(TypeRewriteContext declaringType, MethodDefinition o
9492
declaringType.AssemblyContext.GlobalContext.MethodStartAddresses.Add(FileOffset);
9593
}
9694

97-
public string? UnmangledName { get; private set; }
95+
public Utf8String? UnmangledName { get; private set; }
9896
public string? UnmangledNameWithSignature { get; private set; }
9997

10098
public TypeDefinition? GenericInstantiationsStore { get; private set; }
@@ -137,9 +135,7 @@ public void CtorPhase2()
137135
for (var index = 0; index < genericParams.Count; index++)
138136
{
139137
var oldParameter = genericParams[index];
140-
var genericParameter = new GenericParameter(oldParameter.Name);
141-
if (genericParameter.Name.IsInvalidInSource())
142-
genericParameter.Name = genericParameter.Name.FilterInvalidInSourceChars();
138+
var genericParameter = new GenericParameter(oldParameter.Name.MakeValidInSource());
143139
genericMethodInfoStoreType.GenericParameters.Add(genericParameter);
144140
selfSubstRef.TypeArguments.Add(genericParameter.ToTypeSignature());
145141
var newParameter = NewMethod.GenericParameters[index];
@@ -204,22 +200,18 @@ private string UnmangleMethodName()
204200
if (method.Name.IsObfuscated(DeclaringType.AssemblyContext.GlobalContext.Options))
205201
return UnmangleMethodNameWithSignature();
206202

207-
if (method.Name.IsInvalidInSource())
208-
return method.Name.FilterInvalidInSourceChars();
209-
210-
return method.Name!;
203+
return method.Name.MakeValidInSource();
211204
}
212205

213206
private string ProduceMethodSignatureBase()
214207
{
215208
var method = OriginalMethod;
216209

217-
var name = method.Name;
210+
string name;
218211
if (method.Name.IsObfuscated(DeclaringType.AssemblyContext.GlobalContext.Options))
219212
name = "Method";
220-
221-
if (name.IsInvalidInSource())
222-
name = name.FilterInvalidInSourceChars();
213+
else
214+
name = method.Name.MakeValidInSource();
223215

224216
if (method.Name == "GetType" && method.Parameters.Count == 0)
225217
name = "GetIl2CppType";

Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,7 @@ public TypeRewriteContext GetContextForNewType(TypeDefinition type)
147147
var paramsMethod = new MethodDefinition(newMethod.Name, newMethod.Attributes, MethodSignatureCreator.CreateMethodSignature(newMethod.Attributes, newMethod.Signature!.ReturnType, newMethod.Signature.GenericParameterCount));
148148
foreach (var genericParameter in originalMethod.GenericParameters)
149149
{
150-
var newGenericParameter = new GenericParameter(genericParameter.Name, genericParameter.Attributes);
151-
152-
if (newGenericParameter.Name.IsInvalidInSource())
153-
newGenericParameter.Name = newGenericParameter.Name.FilterInvalidInSourceChars();
150+
var newGenericParameter = new GenericParameter(genericParameter.Name.MakeValidInSource(), genericParameter.Attributes);
154151

155152
foreach (var constraint in genericParameter.Constraints)
156153
{

Il2CppInterop.Generator/Extensions/StringEx.cs

+25-12
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,39 @@ public static string UnSystemify(this Utf8String? str, GeneratorOptions options)
4343
return UnSystemify(str?.Value ?? "", options);
4444
}
4545

46-
public static string FilterInvalidInSourceChars(this string str)
46+
public static string MakeValidInSource(this string str)
4747
{
48-
var chars = str.ToCharArray();
49-
for (var i = 0; i < chars.Length; i++)
48+
if (string.IsNullOrEmpty(str))
49+
return "";
50+
51+
char[]? chars = null;
52+
for (var i = 0; i < str.Length; i++)
5053
{
51-
var it = chars[i];
52-
if (!char.IsDigit(it) && !((it >= 'a' && it <= 'z') || (it >= 'A' && it <= 'Z')) && it != '_' &&
53-
it != '`') chars[i] = '_';
54+
var it = str[i];
55+
if (char.IsDigit(it) || (it is >= 'a' and <= 'z') || (it is >= 'A' and <= 'Z') || it == '_' || it == '`')
56+
continue;
57+
58+
chars ??= str.ToCharArray();
59+
chars[i] = '_';
5460
}
5561

56-
return new string(chars);
62+
var result = chars is null ? str : new string(chars);
63+
return char.IsDigit(result[0]) ? "_" + result : result;
5764
}
5865

59-
public static string FilterInvalidInSourceChars(this Utf8String? str)
66+
public static Utf8String MakeValidInSource(this Utf8String? str)
6067
{
61-
return str?.Value.FilterInvalidInSourceChars() ?? "";
68+
if (Utf8String.IsNullOrEmpty(str))
69+
return Utf8String.Empty;
70+
var result = str.Value.MakeValidInSource();
71+
return result == str ? str : result;
6272
}
6373

64-
public static bool IsInvalidInSource(this string str)
74+
public static bool IsInvalidInSource([NotNullWhen(true)] this string? str)
6575
{
76+
if (str is null)
77+
return false;
78+
6679
for (var i = 0; i < str.Length; i++)
6780
{
6881
var it = str[i];
@@ -73,9 +86,9 @@ public static bool IsInvalidInSource(this string str)
7386
return false;
7487
}
7588

76-
public static bool IsInvalidInSource(this Utf8String? str)
89+
public static bool IsInvalidInSource([NotNullWhen(true)] this Utf8String? str)
7790
{
78-
return IsInvalidInSource(str?.Value ?? "");
91+
return IsInvalidInSource(str?.Value);
7992
}
8093

8194
public static bool IsObfuscated([NotNullWhen(true)] this string? str, GeneratorOptions options)

Il2CppInterop.Generator/Passes/Pass10CreateTypedefs.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,7 @@ internal static (string? Namespace, string Name) GetConvertedTypeName(
101101
return (null, convertedTypeName);
102102
}
103103

104-
if (type.Name.IsInvalidInSource())
105-
return (null, type.Name.FilterInvalidInSourceChars());
106-
107-
return (null, type.Name!);
104+
return (null, type.Name.MakeValidInSource());
108105
}
109106

110107
private static TypeAttributes AdjustAttributes(TypeAttributes typeAttributes)

Il2CppInterop.Generator/Passes/Pass12FillTypedefs.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@ public static void DoPass(RewriteGlobalContext context)
1414
{
1515
foreach (var originalParameter in typeContext.OriginalType.GenericParameters)
1616
{
17-
var newParameter = new GenericParameter(originalParameter.Name);
18-
if (newParameter.Name.IsInvalidInSource())
19-
newParameter.Name = newParameter.Name.FilterInvalidInSourceChars();
17+
var newParameter = new GenericParameter(originalParameter.Name.MakeValidInSource(),
18+
originalParameter.Attributes.StripValueTypeConstraint());
2019
typeContext.NewType.GenericParameters.Add(newParameter);
21-
newParameter.Attributes = originalParameter.Attributes.StripValueTypeConstraint();
2220
}
2321

2422
if (typeContext.OriginalType.IsEnum)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using AsmResolver.DotNet;
2+
using Il2CppInterop.Generator.Contexts;
3+
using Il2CppInterop.Generator.Extensions;
4+
5+
namespace Il2CppInterop.Generator.Passes;
6+
7+
public static class Pass71GenerateEvents
8+
{
9+
public static void DoPass(RewriteGlobalContext context)
10+
{
11+
foreach (var assemblyContext in context.Assemblies)
12+
foreach (var typeContext in assemblyContext.Types)
13+
{
14+
var type = typeContext.OriginalType;
15+
var eventCountsByName = new Dictionary<string, int>();
16+
17+
foreach (var oldEvent in type.Events)
18+
{
19+
var unmangledEventName = UnmangleEventName(assemblyContext, oldEvent, typeContext.NewType, eventCountsByName);
20+
21+
var eventType = assemblyContext.RewriteTypeRef(oldEvent.EventType?.ToTypeSignature());
22+
var @event = new EventDefinition(unmangledEventName, oldEvent.Attributes, eventType.ToTypeDefOrRef());
23+
24+
typeContext.NewType.Events.Add(@event);
25+
26+
@event.SetSemanticMethods(
27+
oldEvent.AddMethod is null ? null : typeContext.GetMethodByOldMethod(oldEvent.AddMethod).NewMethod,
28+
oldEvent.RemoveMethod is null ? null : typeContext.GetMethodByOldMethod(oldEvent.RemoveMethod).NewMethod,
29+
oldEvent.FireMethod is null ? null : typeContext.GetMethodByOldMethod(oldEvent.FireMethod).NewMethod);
30+
}
31+
}
32+
}
33+
34+
private static string UnmangleEventName(AssemblyRewriteContext assemblyContext, EventDefinition @event,
35+
ITypeDefOrRef declaringType, Dictionary<string, int> countsByBaseName)
36+
{
37+
if (assemblyContext.GlobalContext.Options.PassthroughNames ||
38+
!@event.Name.IsObfuscated(assemblyContext.GlobalContext.Options)) return @event.Name!;
39+
40+
var baseName = "event_" + assemblyContext.RewriteTypeRef(@event.EventType?.ToTypeSignature()).GetUnmangledName(@event.DeclaringType);
41+
42+
countsByBaseName.TryGetValue(baseName, out var index);
43+
countsByBaseName[baseName] = index + 1;
44+
45+
var unmangleEventName = baseName + "_" + index;
46+
47+
if (assemblyContext.GlobalContext.Options.RenameMap.TryGetValue(
48+
declaringType.GetNamespacePrefix() + "." + declaringType.Name + "::" + unmangleEventName, out var newNameByType))
49+
{
50+
unmangleEventName = newNameByType;
51+
}
52+
else if (assemblyContext.GlobalContext.Options.RenameMap.TryGetValue(
53+
declaringType.GetNamespacePrefix() + "::" + unmangleEventName, out var newName))
54+
{
55+
unmangleEventName = newName;
56+
}
57+
58+
return unmangleEventName;
59+
}
60+
}

Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs

+25
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,16 @@ public static void DoPass(RewriteGlobalContext context)
124124
var property = GetOrCreateProperty(unityMethod, newMethod);
125125
property.SetMethod = newMethod;
126126
}
127+
else if (unityMethod.IsAddMethod)
128+
{
129+
var @event = GetOrCreateEvent(unityMethod, newMethod);
130+
@event.AddMethod = newMethod;
131+
}
132+
else if (unityMethod.IsRemoveMethod)
133+
{
134+
var @event = GetOrCreateEvent(unityMethod, newMethod);
135+
@event.RemoveMethod = newMethod;
136+
}
127137

128138
var paramsMethod = context.CreateParamsMethod(unityMethod, newMethod, imports,
129139
type => ResolveTypeInNewAssemblies(context, type, imports));
@@ -171,6 +181,21 @@ private static PropertyDefinition GetOrCreateProperty(MethodDefinition unityMeth
171181
return newProperty;
172182
}
173183

184+
private static EventDefinition GetOrCreateEvent(MethodDefinition unityMethod, MethodDefinition newMethod)
185+
{
186+
var unityEvent =
187+
unityMethod.DeclaringType!.Events.Single(
188+
it => it.AddMethod == unityMethod || it.RemoveMethod == unityMethod);
189+
var newEvent = newMethod.DeclaringType!.Events.SingleOrDefault(it => it.Name == unityEvent.Name);
190+
if (newEvent == null)
191+
{
192+
newEvent = new EventDefinition(unityEvent.Name, unityEvent.Attributes, newMethod.Signature!.ParameterTypes.Single().ToTypeDefOrRef());
193+
newMethod.DeclaringType.Events.Add(newEvent);
194+
}
195+
196+
return newEvent;
197+
}
198+
174199
internal static TypeSignature? ResolveTypeInNewAssemblies(RewriteGlobalContext context, TypeSignature? unityType,
175200
RuntimeAssemblyReferences imports, bool useSystemCorlibPrimitives = true)
176201
{

Il2CppInterop.Generator/Runners/InteropAssemblyGenerator.cs

+5
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ public void Run(GeneratorOptions options)
153153
Pass70GenerateProperties.DoPass(rewriteContext);
154154
}
155155

156+
using (new TimingCookie("Creating events"))
157+
{
158+
Pass71GenerateEvents.DoPass(rewriteContext);
159+
}
160+
156161
if (options.UnityBaseLibsDir != null)
157162
{
158163
using (new TimingCookie("Unstripping types"))

0 commit comments

Comments
 (0)