Model and Output: Implement generic type constraints
This commit is contained in:
@@ -104,7 +104,16 @@ namespace Il2CppInspector
|
|||||||
@base.Insert(0, type.GetEnumUnderlyingType().CSharpName);
|
@base.Insert(0, type.GetEnumUnderlyingType().CSharpName);
|
||||||
var baseText = @base.Count > 0 ? " : " + string.Join(", ", @base) : string.Empty;
|
var baseText = @base.Count > 0 ? " : " + string.Join(", ", @base) : string.Empty;
|
||||||
|
|
||||||
writer.Write($"{type.CSharpTypeDeclarationName}{baseText} // TypeDefIndex: {type.Index}\n" + prefix + "{\n");
|
writer.Write($"{type.CSharpTypeDeclarationName}{baseText} // TypeDefIndex: {type.Index}\n");
|
||||||
|
|
||||||
|
if (type.GenericTypeParameters != null)
|
||||||
|
foreach (var gp in type.GenericTypeParameters) {
|
||||||
|
var constraint = gp.GetTypeConstraintsString();
|
||||||
|
if (constraint != string.Empty)
|
||||||
|
writer.Write($"{prefix}\t{constraint}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.Write(prefix + "{\n");
|
||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
if (!type.IsEnum) {
|
if (!type.IsEnum) {
|
||||||
@@ -273,8 +282,16 @@ namespace Il2CppInspector
|
|||||||
writer.Append($"{method.ReturnParameter.GetReturnParameterString()} {method.CSharpName}{method.GetTypeParametersString()}");
|
writer.Append($"{method.ReturnParameter.GetReturnParameterString()} {method.CSharpName}{method.GetTypeParametersString()}");
|
||||||
else
|
else
|
||||||
writer.Append($"{method.CSharpName}{method.ReturnType.CSharpName}");
|
writer.Append($"{method.CSharpName}{method.ReturnType.CSharpName}");
|
||||||
writer.Append("(" + method.GetParametersString());
|
writer.Append("(" + method.GetParametersString() + ")");
|
||||||
writer.Append(");" + (method.VirtualAddress != 0 ? $" // {method.VirtualAddress.ToAddressString()}" : "") + "\n");
|
|
||||||
|
if (method.GenericTypeParameters != null)
|
||||||
|
foreach (var gp in method.GenericTypeParameters) {
|
||||||
|
var constraint = gp.GetTypeConstraintsString();
|
||||||
|
if (constraint != string.Empty)
|
||||||
|
writer.Append($"\n{prefix}\t\t{constraint}");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.Append(";" + (method.VirtualAddress != 0 ? $" // {method.VirtualAddress.ToAddressString()}" : "") + "\n");
|
||||||
|
|
||||||
return writer.ToString();
|
return writer.ToString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,8 +382,8 @@ namespace Il2CppInspector
|
|||||||
public int nameIndex; // StringIndex
|
public int nameIndex; // StringIndex
|
||||||
public short constraintsStart; // GenericParameterConstraintIndex
|
public short constraintsStart; // GenericParameterConstraintIndex
|
||||||
public short constraintsCount;
|
public short constraintsCount;
|
||||||
public ushort num;
|
public ushort num; // Generic parameter position
|
||||||
public ushort flags;
|
public ushort flags; // GenericParameterAttributes
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Il2CppCustomAttributeTypeRange
|
public class Il2CppCustomAttributeTypeRange
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ namespace Il2CppInspector.Reflection
|
|||||||
var container = pkg.GenericContainers[Definition.genericContainerIndex];
|
var container = pkg.GenericContainers[Definition.genericContainerIndex];
|
||||||
|
|
||||||
GenericTypeParameters = pkg.GenericParameters.Skip((int)container.genericParameterStart).Take(container.type_argc).Select(p => new TypeInfo(this, p)).ToList();
|
GenericTypeParameters = pkg.GenericParameters.Skip((int)container.genericParameterStart).Take(container.type_argc).Select(p => new TypeInfo(this, p)).ToList();
|
||||||
|
|
||||||
// TODO: Constraints
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set method attributes
|
// Set method attributes
|
||||||
|
|||||||
@@ -85,6 +85,18 @@ namespace Il2CppInspector.Reflection {
|
|||||||
// Get a field by its name
|
// Get a field by its name
|
||||||
public FieldInfo GetField(string name) => DeclaredFields.FirstOrDefault(f => f.Name == name);
|
public FieldInfo GetField(string name) => DeclaredFields.FirstOrDefault(f => f.Name == name);
|
||||||
|
|
||||||
|
private readonly int genericConstraintIndex;
|
||||||
|
|
||||||
|
private readonly int genericConstraintCount;
|
||||||
|
|
||||||
|
// Get type constraints on a generic parameter
|
||||||
|
public TypeInfo[] GetGenericParameterConstraints() {
|
||||||
|
var types = new TypeInfo[genericConstraintCount];
|
||||||
|
for (int c = 0; c < genericConstraintCount; c++)
|
||||||
|
types[c] = Assembly.Model.GetTypeFromUsage(Assembly.Model.Package.GenericConstraintIndices[genericConstraintIndex + c], MemberTypes.TypeInfo);
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
// Get a method by its name
|
// Get a method by its name
|
||||||
public MethodInfo GetMethod(string name) => DeclaredMethods.FirstOrDefault(m => m.Name == name);
|
public MethodInfo GetMethod(string name) => DeclaredMethods.FirstOrDefault(m => m.Name == name);
|
||||||
|
|
||||||
@@ -126,6 +138,10 @@ namespace Il2CppInspector.Reflection {
|
|||||||
+ (IsArray? "[" + new string(',', GetArrayRank() - 1) + "]" : "")
|
+ (IsArray? "[" + new string(',', GetArrayRank() - 1) + "]" : "")
|
||||||
+ (IsPointer? "*" : "");
|
+ (IsPointer? "*" : "");
|
||||||
|
|
||||||
|
public GenericParameterAttributes GenericParameterAttributes { get; }
|
||||||
|
|
||||||
|
public int GenericParameterPosition { get; }
|
||||||
|
|
||||||
public List<TypeInfo> GenericTypeParameters { get; }
|
public List<TypeInfo> GenericTypeParameters { get; }
|
||||||
|
|
||||||
public List<TypeInfo> GenericTypeArguments { get; }
|
public List<TypeInfo> GenericTypeArguments { get; }
|
||||||
@@ -227,8 +243,6 @@ namespace Il2CppInspector.Reflection {
|
|||||||
var container = pkg.GenericContainers[Definition.genericContainerIndex];
|
var container = pkg.GenericContainers[Definition.genericContainerIndex];
|
||||||
|
|
||||||
GenericTypeParameters = pkg.GenericParameters.Skip((int) container.genericParameterStart).Take(container.type_argc).Select(p => new TypeInfo(this, p)).ToList();
|
GenericTypeParameters = pkg.GenericParameters.Skip((int) container.genericParameterStart).Take(container.type_argc).Select(p => new TypeInfo(this, p)).ToList();
|
||||||
|
|
||||||
// TODO: Constraints
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to global type definition list
|
// Add to global type definition list
|
||||||
@@ -427,14 +441,23 @@ namespace Il2CppInspector.Reflection {
|
|||||||
// Same visibility attributes as declaring type
|
// Same visibility attributes as declaring type
|
||||||
Attributes = declaringType.Attributes;
|
Attributes = declaringType.Attributes;
|
||||||
|
|
||||||
// Same namespace as delcaring type
|
// Same namespace as declaring type
|
||||||
Namespace = declaringType.Namespace;
|
Namespace = declaringType.Namespace;
|
||||||
|
|
||||||
// Base type of object
|
// Special constraints
|
||||||
// TODO: This may change under constraints
|
GenericParameterAttributes = (GenericParameterAttributes) param.flags;
|
||||||
|
|
||||||
|
// Type constraints
|
||||||
|
genericConstraintIndex = param.constraintsStart;
|
||||||
|
genericConstraintCount = param.constraintsCount;
|
||||||
|
|
||||||
|
// Base type of object (set by default)
|
||||||
|
|
||||||
// Name of parameter
|
// Name of parameter
|
||||||
Name = declaringType.Assembly.Model.Package.Strings[param.nameIndex];
|
Name = Assembly.Model.Package.Strings[param.nameIndex];
|
||||||
|
|
||||||
|
// Position
|
||||||
|
GenericParameterPosition = param.num;
|
||||||
|
|
||||||
IsGenericParameter = true;
|
IsGenericParameter = true;
|
||||||
IsGenericType = false;
|
IsGenericType = false;
|
||||||
@@ -494,6 +517,27 @@ namespace Il2CppInspector.Reflection {
|
|||||||
return modifiers.ToString();
|
return modifiers.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetTypeConstraintsString() {
|
||||||
|
if (!IsGenericParameter)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var typeConstraints = GetGenericParameterConstraints();
|
||||||
|
if (GenericParameterAttributes == GenericParameterAttributes.None && typeConstraints.Length == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var constraintList = typeConstraints.Where(c => c.FullName != "System.ValueType").Select(c => c.CSharpTypeDeclarationName).ToList();
|
||||||
|
|
||||||
|
if ((GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint)
|
||||||
|
constraintList.Add("struct");
|
||||||
|
if ((GenericParameterAttributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint)
|
||||||
|
constraintList.Add("class");
|
||||||
|
if ((GenericParameterAttributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint
|
||||||
|
&& !constraintList.Contains("struct"))
|
||||||
|
constraintList.Add("new()");
|
||||||
|
|
||||||
|
return "where " + Name + " : " + string.Join(", ", constraintList);
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString() => Name;
|
public override string ToString() => Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user