Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup name validity #177

Merged
merged 4 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ private string UnmangleFieldNameBase(FieldDefinition field, GeneratorOptions opt

if (!field.Name.IsObfuscated(options))
{
if (!field.Name.IsInvalidInSource())
return field.Name!;
return field.Name.FilterInvalidInSourceChars();
return field.Name.MakeValidInSource();
}

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

if (!field.Name.IsObfuscated(options))
{
if (!field.Name.IsInvalidInSource())
return field.Name!;
return field.Name.FilterInvalidInSourceChars();
return field.Name.MakeValidInSource();
}

if (renamedFieldCounts == null) throw new ArgumentNullException(nameof(renamedFieldCounts));
Expand Down
28 changes: 10 additions & 18 deletions Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Text;
using AsmResolver;
using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
using AsmResolver.PE.DotNet.Metadata.Tables;
Expand Down Expand Up @@ -73,12 +74,9 @@ public MethodRewriteContext(TypeRewriteContext declaringType, MethodDefinition o

foreach (var oldParameter in genericParams)
{
var genericParameter = new GenericParameter(oldParameter.Name);
genericParameter.Attributes = oldParameter.Attributes.StripValueTypeConstraint();
newMethod.GenericParameters.Add(genericParameter);

if (genericParameter.Name.IsInvalidInSource())
genericParameter.Name = genericParameter.Name.FilterInvalidInSourceChars();
newMethod.GenericParameters.Add(new GenericParameter(
oldParameter.Name.MakeValidInSource(),
oldParameter.Attributes.StripValueTypeConstraint()));
}
}

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

public string? UnmangledName { get; private set; }
public Utf8String? UnmangledName { get; private set; }
public string? UnmangledNameWithSignature { get; private set; }

public TypeDefinition? GenericInstantiationsStore { get; private set; }
Expand Down Expand Up @@ -137,9 +135,7 @@ public void CtorPhase2()
for (var index = 0; index < genericParams.Count; index++)
{
var oldParameter = genericParams[index];
var genericParameter = new GenericParameter(oldParameter.Name);
if (genericParameter.Name.IsInvalidInSource())
genericParameter.Name = genericParameter.Name.FilterInvalidInSourceChars();
var genericParameter = new GenericParameter(oldParameter.Name.MakeValidInSource());
genericMethodInfoStoreType.GenericParameters.Add(genericParameter);
selfSubstRef.TypeArguments.Add(genericParameter.ToTypeSignature());
var newParameter = NewMethod.GenericParameters[index];
Expand Down Expand Up @@ -204,22 +200,18 @@ private string UnmangleMethodName()
if (method.Name.IsObfuscated(DeclaringType.AssemblyContext.GlobalContext.Options))
return UnmangleMethodNameWithSignature();

if (method.Name.IsInvalidInSource())
return method.Name.FilterInvalidInSourceChars();

return method.Name!;
return method.Name.MakeValidInSource();
}

private string ProduceMethodSignatureBase()
{
var method = OriginalMethod;

var name = method.Name;
string name;
if (method.Name.IsObfuscated(DeclaringType.AssemblyContext.GlobalContext.Options))
name = "Method";

if (name.IsInvalidInSource())
name = name.FilterInvalidInSourceChars();
else
name = method.Name.MakeValidInSource();

if (method.Name == "GetType" && method.Parameters.Count == 0)
name = "GetIl2CppType";
Expand Down
5 changes: 1 addition & 4 deletions Il2CppInterop.Generator/Contexts/RewriteGlobalContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,7 @@ public TypeRewriteContext GetContextForNewType(TypeDefinition type)
var paramsMethod = new MethodDefinition(newMethod.Name, newMethod.Attributes, MethodSignatureCreator.CreateMethodSignature(newMethod.Attributes, newMethod.Signature!.ReturnType, newMethod.Signature.GenericParameterCount));
foreach (var genericParameter in originalMethod.GenericParameters)
{
var newGenericParameter = new GenericParameter(genericParameter.Name, genericParameter.Attributes);

if (newGenericParameter.Name.IsInvalidInSource())
newGenericParameter.Name = newGenericParameter.Name.FilterInvalidInSourceChars();
var newGenericParameter = new GenericParameter(genericParameter.Name.MakeValidInSource(), genericParameter.Attributes);

foreach (var constraint in genericParameter.Constraints)
{
Expand Down
82 changes: 68 additions & 14 deletions Il2CppInterop.Generator/Extensions/StringEx.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using AsmResolver;
Expand Down Expand Up @@ -43,26 +44,79 @@ public static string UnSystemify(this Utf8String? str, GeneratorOptions options)
return UnSystemify(str?.Value ?? "", options);
}

public static string FilterInvalidInSourceChars(this string str)
public static string MakeValidInSource(this string str)
{
var chars = str.ToCharArray();
for (var i = 0; i < chars.Length; i++)
if (string.IsNullOrEmpty(str))
return "";

char[]? chars = null;
for (var i = 0; i < str.Length; i++)
{
var it = chars[i];
if (!char.IsDigit(it) && !((it >= 'a' && it <= 'z') || (it >= 'A' && it <= 'Z')) && it != '_' &&
it != '`') chars[i] = '_';
var it = str[i];
if (IsValidInSource(it))
continue;

chars ??= str.ToCharArray();
chars[i] = '_';
}

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

public static string FilterInvalidInSourceChars(this Utf8String? str)
private static bool IsValidInSource(char c) => char.IsDigit(c) || (c is >= 'a' and <= 'z') || (c is >= 'A' and <= 'Z') || c == '_' || c == '`';

public static Utf8String MakeValidInSource(this Utf8String? str)
{
return str?.Value.FilterInvalidInSourceChars() ?? "";
if (Utf8String.IsNullOrEmpty(str))
return Utf8String.Empty;

ReadOnlySpan<byte> data = str.GetBytesUnsafe();

var length = data.Length;
byte[]? rentedArray = null;
Span<byte> rentedArraySpan = default;

if (char.IsDigit((char)data[0]))
{
length++;
rentedArray = ArrayPool<byte>.Shared.Rent(length);
rentedArray[0] = (byte)'_';
rentedArraySpan = rentedArray.AsSpan(1);
data.CopyTo(rentedArraySpan);
}

for (var i = 0; i < data.Length; i++)
{
if (IsValidInSource((char)data[i]))
continue;

if (rentedArray is null)
{
rentedArray = ArrayPool<byte>.Shared.Rent(length);
rentedArraySpan = rentedArray.AsSpan();
data.CopyTo(rentedArraySpan);
}
rentedArraySpan[i] = (byte)'_';
}

if (rentedArray is not null)
{
var result = new Utf8String(rentedArray, 0, length);
ArrayPool<byte>.Shared.Return(rentedArray);
return result;
}
else
{
return str;
}
}

public static bool IsInvalidInSource(this string str)
public static bool IsInvalidInSource([NotNullWhen(true)] this string? str)
{
if (str is null)
return false;

for (var i = 0; i < str.Length; i++)
{
var it = str[i];
Expand All @@ -73,9 +127,9 @@ public static bool IsInvalidInSource(this string str)
return false;
}

public static bool IsInvalidInSource(this Utf8String? str)
public static bool IsInvalidInSource([NotNullWhen(true)] this Utf8String? str)
{
return IsInvalidInSource(str?.Value ?? "");
return IsInvalidInSource(str?.Value);
}

public static bool IsObfuscated([NotNullWhen(true)] this string? str, GeneratorOptions options)
Expand Down Expand Up @@ -149,9 +203,9 @@ public static string GetUnmangledName(this TypeSignature typeRef, TypeDefinition
else if (typeRef is GenericParameterSignature genericParameter)
{
if (genericParameter.ParameterType == GenericParameterType.Type)
builder.Append(declaringType!.GenericParameters[genericParameter.Index].Name);
builder.Append(declaringType!.GenericParameters[genericParameter.Index].Name.MakeValidInSource());
else
builder.Append(declaringMethod!.GenericParameters[genericParameter.Index].Name);
builder.Append(declaringMethod!.GenericParameters[genericParameter.Index].Name.MakeValidInSource());
}
else
{
Expand Down
3 changes: 3 additions & 0 deletions Il2CppInterop.Generator/Il2CppInterop.Generator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

<ItemGroup>
<PackageReference Include="AsmResolver.DotNet" Version="6.0.0-beta.1" />
<PackageReference Include="MonoMod.Backports" Version="1.1.2">
<Aliases>MonoModBackports</Aliases><!-- Transitive dependency from AsmResolver. Extern alias prevents it from affecting us. -->
</PackageReference>
<PackageReference Include="PolySharp" Version="1.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
5 changes: 1 addition & 4 deletions Il2CppInterop.Generator/Passes/Pass10CreateTypedefs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,7 @@ internal static (string? Namespace, string Name) GetConvertedTypeName(
return (null, convertedTypeName);
}

if (type.Name.IsInvalidInSource())
return (null, type.Name.FilterInvalidInSourceChars());

return (null, type.Name!);
return (null, type.Name.MakeValidInSource());
}

private static TypeAttributes AdjustAttributes(TypeAttributes typeAttributes)
Expand Down
6 changes: 2 additions & 4 deletions Il2CppInterop.Generator/Passes/Pass12FillTypedefs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ public static void DoPass(RewriteGlobalContext context)
{
foreach (var originalParameter in typeContext.OriginalType.GenericParameters)
{
var newParameter = new GenericParameter(originalParameter.Name);
if (newParameter.Name.IsInvalidInSource())
newParameter.Name = newParameter.Name.FilterInvalidInSourceChars();
var newParameter = new GenericParameter(originalParameter.Name.MakeValidInSource(),
originalParameter.Attributes.StripValueTypeConstraint());
typeContext.NewType.GenericParameters.Add(newParameter);
newParameter.Attributes = originalParameter.Attributes.StripValueTypeConstraint();
}

if (typeContext.OriginalType.IsEnum)
Expand Down
2 changes: 1 addition & 1 deletion Il2CppInterop.Generator/Passes/Pass80UnstripMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static void DoPass(RewriteGlobalContext context)

foreach (var unityMethodGenericParameter in unityMethod.GenericParameters)
{
var newParameter = new GenericParameter(unityMethodGenericParameter.Name);
var newParameter = new GenericParameter(unityMethodGenericParameter.Name.MakeValidInSource());
newParameter.Attributes = unityMethodGenericParameter.Attributes;
foreach (var genericParameterConstraint in unityMethodGenericParameter.Constraints)
{
Expand Down
Loading