Skip to content

Commit 9536ccf

Browse files
committed
Fallback when generics are unavailable
1 parent 27870da commit 9536ccf

File tree

5 files changed

+260
-300
lines changed

5 files changed

+260
-300
lines changed

csharp-api/AssemblyGenerator/ClassGenerator.cs

Lines changed: 11 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@
1919
using REFrameworkNET.Attributes;
2020

2121
public class ClassGenerator {
22-
public class PseudoProperty {
22+
public class PseudoProperty(TypeDefinition type) {
2323
public REFrameworkNET.Method? getter;
2424
public REFrameworkNET.Method? setter;
25-
public REFrameworkNET.TypeDefinition? type;
26-
public bool indexer = false;
25+
public REFrameworkNET.TypeDefinition type = type;
2726
public REFrameworkNET.TypeDefinition? indexType;
2827
};
2928

@@ -33,7 +32,6 @@ public class PseudoProperty {
3332
private List<REFrameworkNET.Method> methods = [];
3433
private List<REFrameworkNET.Field> fields = [];
3534
private InterfaceDeclarationSyntax typeDeclaration;
36-
private bool addedNewKeyword = false;
3735
private bool generic = false;
3836

3937

@@ -43,11 +41,6 @@ public TypeDeclarationSyntax? TypeDeclaration {
4341
}
4442
}
4543

46-
public bool AddedNewKeyword {
47-
get {
48-
return addedNewKeyword;
49-
}
50-
}
5144

5245
public ClassGenerator(REFrameworkNET.TypeDefinition t_, bool? pGeneric = null) {
5346
t = t_;
@@ -75,43 +68,35 @@ public ClassGenerator(REFrameworkNET.TypeDefinition t_, bool? pGeneric = null) {
7568
// Add the getter to the pseudo property (create if it doesn't exist)
7669
var propertyName = method.Name[4..];
7770
if (!pseudoProperties.ContainsKey(propertyName)) {
78-
pseudoProperties[propertyName] = new PseudoProperty();
71+
pseudoProperties[propertyName] = new PseudoProperty(method.ReturnType);
7972
}
8073

8174
pseudoProperties[propertyName].getter = method;
82-
pseudoProperties[propertyName].type = method.ReturnType;
8375
} else if (method.Parameters.Count == 1 && method.Name == "get_Item") {
8476
// This is an indexer property
8577
var propertyName = method.Name[4..];
8678
if (!pseudoProperties.ContainsKey(propertyName)) {
87-
pseudoProperties[propertyName] = new PseudoProperty();
79+
pseudoProperties[propertyName] = new PseudoProperty(method.ReturnType);
8880
}
89-
9081
pseudoProperties[propertyName].getter = method;
91-
pseudoProperties[propertyName].type = method.ReturnType;
92-
pseudoProperties[propertyName].indexer = true;
9382
pseudoProperties[propertyName].indexType = method.Parameters[0].Type;
9483
}
9584
} else if (method.Name.StartsWith("set_")) {
9685
if (method.Parameters.Count == 1) {
9786
// Add the setter to the pseudo property (create if it doesn't exist)
9887
var propertyName = method.Name[4..];
9988
if (!pseudoProperties.ContainsKey(propertyName)) {
100-
pseudoProperties[propertyName] = new PseudoProperty();
89+
pseudoProperties[propertyName] = new PseudoProperty(method.Parameters[0].Type);
10190
}
102-
10391
pseudoProperties[propertyName].setter = method;
104-
pseudoProperties[propertyName].type = method.Parameters[0].Type;
10592
} else if (method.Parameters.Count == 2 && method.Name == "set_Item") {
10693
// This is an indexer property
10794
var propertyName = method.Name[4..];
10895
if (!pseudoProperties.ContainsKey(propertyName)) {
109-
pseudoProperties[propertyName] = new PseudoProperty();
96+
pseudoProperties[propertyName] = new PseudoProperty(method.Parameters[1].Type);
11097
}
11198

11299
pseudoProperties[propertyName].setter = method;
113-
pseudoProperties[propertyName].type = method.Parameters[1].Type;
114-
pseudoProperties[propertyName].indexer = true;
115100
pseudoProperties[propertyName].indexType = method.Parameters[0].Type;
116101
}
117102
} else {
@@ -181,21 +166,14 @@ private void Generate() {
181166

182167
if (generic) {
183168
var arguments = t.GenericArguments ?? [];
184-
var parentGenericCount = Math.Max(0, arguments.Length - count);
169+
var parentGenericCount = Math.Max(0, arguments.Count() - count);
185170
var argumentList = new List<TypeParameterSyntax>();
186-
for (int i = parentGenericCount; i < arguments.Length; ++i) {
171+
for (int i = parentGenericCount; i < arguments.Count(); ++i) {
187172
argumentList.Add(TypeParameter(GenericNames[i]));
188173
}
189174
typeDeclaration = typeDeclaration.AddTypeParameterListParameters([.. argumentList]);
190175
}
191176

192-
193-
// Check if we need to add the new keyword to this.
194-
if (AssemblyGenerator.NestedTypeExistsInParent(t)) {
195-
typeDeclaration = typeDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.NewKeyword));
196-
addedNewKeyword = true;
197-
}
198-
199177
// Set up base types
200178
BaseTypeSyntax[] baseTypes = TypeHandler.ParentTypes(t);
201179
typeDeclaration = typeDeclaration.AddBaseListTypes(baseTypes);
@@ -207,25 +185,15 @@ private void Generate() {
207185
VariableDeclarator("REFProxy")
208186
.WithInitializer(EqualsValueClause(ParseExpression("REFType.As<" + REFrameworkNET.AssemblyGenerator.CorrectTypeName(t.FullName) + ">()"))));
209187

210-
var refProxyFieldDecl = SyntaxFactory.FieldDeclaration(refProxyVarDecl).AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword));
211188

212-
213-
// var typeIdExpr = GenericDictExpr((t) => t.Index);
214189
var refTypeName = (FieldDeclarationSyntax)ParseMemberDeclaration($"public static readonly string REFTypeName = {GenericTypeNameExpr()};")!;
215-
if (baseTypes.Length > 0)
216-
refTypeName = refTypeName.AddModifiers(Token(SyntaxKind.NewKeyword));
217190
typeDeclaration = typeDeclaration.AddMembers(refTypeName);
218191

219192
// Add a static field to the class that holds the REFrameworkNET.TypeDefinition
220193
var refTypeFieldDecl = ParseMemberDeclaration(
221194
$"public static readonly global::REFrameworkNET.TypeDefinition REFType = global::REFrameworkNET.TDB.Get().FindType(REFTypeName);"
222195
)!;
223-
if (baseTypes.Length > 0) {
224-
refTypeFieldDecl = refTypeFieldDecl.AddModifiers(SyntaxFactory.Token(SyntaxKind.NewKeyword));
225-
}
226196
typeDeclaration = typeDeclaration.AddMembers(refTypeFieldDecl);
227-
//typeDeclaration = typeDeclaration.AddMembers(refProxyFieldDecl);
228-
229197

230198

231199
GenerateMethods();
@@ -307,7 +275,7 @@ private void GenerateProperties() {
307275
BasePropertyDeclarationSyntax propertyDeclaration = SyntaxFactory.PropertyDeclaration(propertyType, propertyName)
308276
.AddModifiers([SyntaxFactory.Token(SyntaxKind.PublicKeyword)]);
309277

310-
if (property.Value.indexer) {
278+
if (property.Value.indexType is not null) {
311279
ParameterSyntax parameter = SyntaxFactory
312280
.Parameter(SyntaxFactory.Identifier("index"))
313281
.WithType(TypeHandler.ProperType(property.Value.indexType));
@@ -317,7 +285,6 @@ private void GenerateProperties() {
317285
.AddParameterListParameters(parameter);
318286
}
319287

320-
bool shouldAddNewKeyword = false;
321288
bool shouldAddStaticKeyword = false;
322289

323290
if (property.Value.getter != null) {
@@ -356,10 +323,6 @@ private void GenerateProperties() {
356323
propertyDeclaration = propertyDeclaration.AddAccessorListAccessors(getter);
357324

358325
var getterExtension = Il2CppDump.GetMethodExtension(property.Value.getter);
359-
if (getterExtension?.MatchingParentMethods.Any() ?? false) {
360-
shouldAddNewKeyword = true;
361-
}
362-
363326
}
364327

365328
if (property.Value.setter != null) {
@@ -398,19 +361,11 @@ private void GenerateProperties() {
398361
propertyDeclaration = propertyDeclaration.AddAccessorListAccessors(setter);
399362

400363
var setterExtension = Il2CppDump.GetMethodExtension(property.Value.setter);
401-
if (setterExtension?.MatchingParentMethods.Any() ?? false) {
402-
shouldAddNewKeyword = true;
403-
}
404364
}
405365

406366
if (shouldAddStaticKeyword) {
407367
propertyDeclaration = propertyDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword));
408368
}
409-
410-
if (shouldAddNewKeyword) {
411-
propertyDeclaration = propertyDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.NewKeyword));
412-
}
413-
414369
return propertyDeclaration;
415370
})
416371
.ToArray();
@@ -463,7 +418,8 @@ private void GenerateFields() {
463418
// Some kind of limitation in the runtime prevents too many methods in the class
464419
if (totalFields >= (ushort.MaxValue - 15) / 2) {
465420
System.Console.WriteLine("Skipping fields in " + t.FullName + " because it has too many fields (" + fields.Count + ")");
466-
break;
421+
// break;
422+
return;
467423
}
468424
}
469425
List<FieldDeclarationSyntax> internalFieldDeclarations = [];
@@ -531,17 +487,6 @@ private void GenerateFields() {
531487
}
532488

533489
propertyDeclaration = propertyDeclaration.AddAccessorListAccessors(getter, setter);
534-
535-
// Search for k__BackingField version and the corrected version
536-
if (this.t.ParentType != null) {
537-
var matchingField = this.t.ParentType.FindField(fieldName);
538-
matchingField ??= this.t.ParentType.FindField(field.Name);
539-
var matchingMethod = this.t.ParentType.FindMethod("get_" + fieldName);
540-
matchingMethod ??= this.t.ParentType.FindMethod("set_" + fieldName);
541-
if (matchingMethod?.GetMatchingParentMethods().Any() ?? false) {
542-
propertyDeclaration = propertyDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.NewKeyword));
543-
}
544-
}
545490
return propertyDeclaration;
546491
})
547492
.ToArray();
@@ -804,12 +749,6 @@ private void GenerateMethods() {
804749
}
805750

806751
seenMethodSignatures.Add(simpleMethodSignature);
807-
808-
if (methodExtension?.MatchingParentMethods.Any() ?? false) {
809-
methodDeclaration = methodDeclaration.AddModifiers(Token(SyntaxKind.NewKeyword));
810-
}
811-
812-
813752
return methodDeclaration;
814753
})
815754
.Where(method => method != null)
@@ -833,178 +772,3 @@ private void GenerateMethods() {
833772

834773

835774
}
836-
837-
class TypeHandler {
838-
public static TypeSyntax VoidType() => PredefinedType(Token(SyntaxKind.VoidKeyword));
839-
public static TypeSyntax ObjType() => PredefinedType(Token(SyntaxKind.ObjectKeyword));
840-
public static Dictionary<string, TypeSyntax> Predefined = new() {
841-
["System.Single"] = ParseTypeName("float"),
842-
["System.Double"] = ParseTypeName("double"),
843-
["System.Int32"] = ParseTypeName("int"),
844-
["System.UInt32"] = ParseTypeName("uint"),
845-
["System.Int16"] = ParseTypeName("short"),
846-
["System.UInt16"] = ParseTypeName("ushort"),
847-
["System.Byte"] = ParseTypeName("byte"),
848-
["System.SByte"] = ParseTypeName("sbyte"),
849-
["System.Char"] = ParseTypeName("char"),
850-
["System.Int64"] = ParseTypeName("long"),
851-
["System.IntPtr"] = ParseTypeName("long"),
852-
["System.UInt64"] = ParseTypeName("ulong"),
853-
["System.UIntPtr"] = ParseTypeName("ulong"),
854-
["System.Boolean"] = ParseTypeName("bool"),
855-
["System.String"] = ParseTypeName("string"),
856-
["via.clr.ManagedObject"] = ObjType(),
857-
["System.Object"] = ObjType(),
858-
["System.Void"] = VoidType(),
859-
["!0"] = ParseTypeName("T"),
860-
["!1"] = ParseTypeName("U"),
861-
["!2"] = ParseTypeName("V"),
862-
["!3"] = ParseTypeName("W"),
863-
["!4"] = ParseTypeName("X"),
864-
["!5"] = ParseTypeName("Y"),
865-
["!6"] = ParseTypeName("Z"),
866-
["!7"] = ParseTypeName("P7"),
867-
["!8"] = ParseTypeName("P8"),
868-
["!9"] = ParseTypeName("P9"),
869-
};
870-
871-
public static Dictionary<uint, TypeSyntax> Cache = new();
872-
873-
public static (string, int) BaseTypeName(string baseName) {
874-
if (baseName.Split('`').ToArray() is [var name, var count])
875-
return (name, int.Parse(count));
876-
return (baseName, 0);
877-
878-
}
879-
880-
public static BaseTypeSyntax[] ParentTypes(TypeDefinition type) {
881-
List<BaseTypeSyntax> parents = new();
882-
var parentType = type.ParentType;
883-
while (parentType != null) {
884-
if (parentType.Name == "") break;
885-
if (parentType.FullName == "System.Object") {
886-
parents.Insert(0, SimpleBaseType(ParseTypeName("global::_System.Object")));
887-
break;
888-
}
889-
var baseType = SimpleBaseType(ProperType(parentType));
890-
parents.Insert(0, baseType);
891-
parentType = parentType.ParentType;
892-
}
893-
return parents.ToArray();
894-
}
895-
896-
public static TypeSyntax ProperType(TypeDefinition type) {
897-
if (type is null) return VoidType();
898-
if (type.Name.StartsWith("<")) return ObjType();
899-
if (type.Name.StartsWith("!!")) return ObjType();
900-
901-
if (Predefined.ContainsKey(type.FullName))
902-
return Predefined[type.FullName];
903-
if (Cache.ContainsKey(type.Index))
904-
return Cache[type.Index];
905-
return ObjType();
906-
}
907-
908-
public static string[] NameHierarchy(TypeDefinition type) {
909-
var typeList = new List<string>();
910-
while (true) {
911-
typeList.Insert(0, type.Name);
912-
if (type.DeclaringType is null || type.DeclaringType == type)
913-
break;
914-
type = type.DeclaringType;
915-
}
916-
if (type.Namespace is not null && type.Namespace.Any()) {
917-
typeList.Insert(0, type.Namespace);
918-
} else {
919-
typeList.Insert(0, "_");
920-
}
921-
return [.. typeList];
922-
}
923-
924-
static TypeSyntax BuildProperType(REFrameworkNET.TypeDefinition? targetType) {
925-
926-
if (targetType is null) return VoidType();
927-
if (targetType.Name.StartsWith("<")) return ObjType();
928-
if (targetType.Name.StartsWith("!!")) return ObjType();
929-
930-
if (Predefined.ContainsKey(targetType.FullName))
931-
return Predefined[targetType.FullName];
932-
if (Cache.ContainsKey(targetType.Index))
933-
return Cache[targetType.Index];
934-
935-
if (targetType.GetElementType() is TypeDefinition elemType) {
936-
var elem = BuildProperType(elemType);
937-
var arraySyntax = QualifiedName(
938-
ParseName("global::_System.Array"),
939-
GenericName("Impl")
940-
.AddTypeArgumentListArguments([elem])
941-
);
942-
Cache[targetType.Index] = arraySyntax;
943-
return arraySyntax;
944-
}
945-
Cache[targetType.Index] = ObjType();
946-
947-
var typeList = NameHierarchy(targetType);
948-
int genericIndex = 0;
949-
var generics = targetType.GenericArguments ?? [];
950-
var toParse = string.Join(".", typeList.Select(tName => {
951-
var (name, count) = BaseTypeName(tName);
952-
if (count == 0) return name;
953-
name += "<";
954-
for (int i = 0; i < count; ++i) {
955-
if (i > 0) name += ",";
956-
if (i + genericIndex >= generics.Length) {
957-
name += "UNKN";
958-
continue;
959-
}
960-
name += ProperType(generics[i + genericIndex]).ToFullString();
961-
}
962-
name += ">";
963-
genericIndex += count;
964-
return name;
965-
}
966-
));
967-
if (toParse.StartsWith("System"))
968-
toParse = "_" + toParse;
969-
var parsed = ParseTypeName($"global::{toParse}");
970-
Cache[targetType.Index] = parsed;
971-
return parsed;
972-
}
973-
974-
public static void BuildProperTypes() {
975-
foreach (TypeDefinition type in API.GetTDB().Types) {
976-
BuildProperType(type);
977-
// Special case delegates again
978-
if (!(type.FullName.StartsWith("System.Action") || type.FullName.StartsWith("System.Func"))) {
979-
if (type.IsGenericType()) BuildProperType(type.GetGenericTypeDefinition());
980-
}
981-
}
982-
API.LogInfo("Built proper types");
983-
}
984-
985-
public static MemberDeclarationSyntax? GenerateType(TypeDefinition t) {
986-
987-
if (t.Name == "") return null;
988-
if (t.FullName.EndsWith("[]")) return null;
989-
if (t.Name.StartsWith("<")) return null;
990-
if (t.IsGenericType() && !t.IsGenericTypeDefinition()) return null;
991-
992-
// Enum
993-
if (t.IsEnum()) {
994-
var (baseName, _) = TypeHandler.BaseTypeName(t.Name);
995-
var nestedEnumGenerator = new EnumGenerator(baseName, t);
996-
return nestedEnumGenerator.EnumDeclaration;
997-
}
998-
var nestedGenerator = new ClassGenerator(t);
999-
return nestedGenerator.TypeDeclaration;
1000-
}
1001-
1002-
public static MemberDeclarationSyntax[] GenerateNestedTypes(TypeDefinition t) {
1003-
var nestedTypes = Il2CppDump.GetTypeExtension(t)?.NestedTypes;
1004-
return nestedTypes?
1005-
.Select(GenerateType)
1006-
.Where(t => t is not null)
1007-
.Select(t => t!)
1008-
.ToArray() ?? [];
1009-
}
1010-
}

0 commit comments

Comments
 (0)