Update getScopedFullName for generic params + update README

This commit is contained in:
LukeFZ
2024-02-25 11:32:20 +01:00
parent 0f7cd027c3
commit 2a492e02ba
2 changed files with 26 additions and 14 deletions

View File

@@ -412,9 +412,14 @@ namespace Il2CppInspector.Reflection
} }
// Returns the minimally qualified type name required to refer to this type within the specified scope // Returns the minimally qualified type name required to refer to this type within the specified scope
private string getScopedFullName(Scope scope) { private string getScopedFullName(Scope scope)
{
// Generic type parameters take precedence over all other names, so if FullName is null (== generic) we can just return the name itself
if (IsGenericParameter)
return this.Name;
// This is the type to be used (generic type parameters have a null FullName) // This is the type to be used (generic type parameters have a null FullName)
var usedType = FullName?.Replace('+', '.') ?? Name; var usedType = FullName.Replace('+', '.');
// This is the scope in which this type is currently being used // This is the scope in which this type is currently being used
// If Scope.Current is null, our scope is at the assembly level // If Scope.Current is null, our scope is at the assembly level
@@ -439,14 +444,14 @@ namespace Il2CppInspector.Reflection
declaringScope += "."; declaringScope += ".";
while (usingScope.IndexOf('.', diff) == declaringScope.IndexOf('.', diff) while (usingScope.IndexOf('.', diff) == declaringScope.IndexOf('.', diff)
&& usingScope.IndexOf('.', diff) != -1 && usingScope.IndexOf('.', diff) != -1
&& usingScope.Substring(0, usingScope.IndexOf('.', diff)) && usingScope[..usingScope.IndexOf('.', diff)]
== declaringScope.Substring(0, declaringScope.IndexOf('.', diff))) == declaringScope[..declaringScope.IndexOf('.', diff)])
diff = usingScope.IndexOf('.', diff) + 1; diff = usingScope.IndexOf('.', diff) + 1;
usingScope = usingScope.Remove(usingScope.Length - 1); usingScope = usingScope.Remove(usingScope.Length - 1);
declaringScope = declaringScope.Remove(declaringScope.Length - 1); declaringScope = declaringScope.Remove(declaringScope.Length - 1);
// This is the mutual root namespace and optionally nested types that the two scopes share // This is the mutual root namespace and optionally nested types that the two scopes share
var mutualRootScope = usingScope.Substring(0, diff - 1); var mutualRootScope = usingScope[..(diff - 1)];
// Determine if the using scope is a child of the declaring scope (always a child if declaring scope is empty) // Determine if the using scope is a child of the declaring scope (always a child if declaring scope is empty)
var usingScopeIsChildOfDeclaringScope = string.IsNullOrEmpty(declaringScope) || (usingScope + ".").StartsWith(declaringScope + "."); var usingScopeIsChildOfDeclaringScope = string.IsNullOrEmpty(declaringScope) || (usingScope + ".").StartsWith(declaringScope + ".");
@@ -472,7 +477,7 @@ namespace Il2CppInspector.Reflection
var minimallyScopedName = var minimallyScopedName =
declaringScope == mutualRootScope ? base.Name : declaringScope == mutualRootScope ? base.Name :
string.IsNullOrEmpty(mutualRootScope) ? declaringScope + '.' + base.Name : string.IsNullOrEmpty(mutualRootScope) ? declaringScope + '.' + base.Name :
declaringScope.Substring(mutualRootScope.Length + 1) + '.' + base.Name; string.Concat(declaringScope.AsSpan(mutualRootScope.Length + 1), ".", base.Name);
// Find the outermost type name if the wanted type is a nested type (if we need it below) // Find the outermost type name if the wanted type is a nested type (if we need it below)
string outerTypeName = ""; string outerTypeName = "";
@@ -487,7 +492,7 @@ namespace Il2CppInspector.Reflection
// Otherwise, we just try the unqualified outer (least nested) type name to make sure it's accessible // Otherwise, we just try the unqualified outer (least nested) type name to make sure it's accessible
// and revert to the fully qualified name if it's hidden // and revert to the fully qualified name if it's hidden
var nsAndTypeHierarchy = usingScopeIsChildOfDeclaringScope ? var nsAndTypeHierarchy = usingScopeIsChildOfDeclaringScope ?
usingDirective.Split('.').Append(minimallyScopedName).ToArray() [.. usingDirective.Split('.'), minimallyScopedName]
: new[] { outerTypeName }; : new[] { outerTypeName };
var hidden = true; var hidden = true;
@@ -548,24 +553,24 @@ namespace Il2CppInspector.Reflection
.Select(ns => (!string.IsNullOrEmpty(ns)? ns + "." : "") + minimallyScopedName).ToList() ?? new List<string>(); .Select(ns => (!string.IsNullOrEmpty(ns)? ns + "." : "") + minimallyScopedName).ToList() ?? new List<string>();
if (Assembly.Model.Namespaces.Intersect(checkNamespaces).Any()) if (Assembly.Model.Namespaces.Intersect(checkNamespaces).Any())
minimallyScopedName = mutualRootScope.Length > 0 ? usedType.Substring(mutualRootScope.Length + 1) : usedType; minimallyScopedName = mutualRootScope.Length > 0 ? usedType[(mutualRootScope.Length + 1)..] : usedType;
// Check current namespace and all ancestors too // Check current namespace and all ancestors too
else { else {
checkNamespaces.Clear(); checkNamespaces.Clear();
var ancestorUsingScope = "." + usingScope; var ancestorUsingScope = "." + usingScope;
while (ancestorUsingScope.IndexOf(".", StringComparison.Ordinal) != -1) { while (ancestorUsingScope.Contains('.')) {
ancestorUsingScope = ancestorUsingScope.Substring(0, ancestorUsingScope.LastIndexOf(".", StringComparison.Ordinal)); ancestorUsingScope = ancestorUsingScope[..ancestorUsingScope.LastIndexOf('.')];
checkNamespaces.Add((ancestorUsingScope.Length > 0 ? ancestorUsingScope.Substring(1) + "." : "") + minimallyScopedName); checkNamespaces.Add((ancestorUsingScope.Length > 0 ? ancestorUsingScope[1..] + "." : "") + minimallyScopedName);
} }
if (Assembly.Model.Namespaces.Intersect(checkNamespaces).Any()) if (Assembly.Model.Namespaces.Intersect(checkNamespaces).Any())
minimallyScopedName = mutualRootScope.Length > 0 ? usedType.Substring(mutualRootScope.Length + 1) : "global::" + usedType; minimallyScopedName = mutualRootScope.Length > 0 ? usedType[(mutualRootScope.Length + 1)..] : "global::" + usedType;
} }
// If the final name starts with ".", it's a reference to the global namespace (ie. unnamed root namespace) // If the final name starts with ".", it's a reference to the global namespace (ie. unnamed root namespace)
if (minimallyScopedName.StartsWith(".")) if (minimallyScopedName.StartsWith('.'))
minimallyScopedName = "global::" + minimallyScopedName.Substring(1); minimallyScopedName = "global::" + minimallyScopedName[1..];
return minimallyScopedName; return minimallyScopedName;
} }

View File

@@ -20,6 +20,13 @@ This is a continuation of [Il2CppInspector, by djkaty](https://github.com/djkaty
- Made ValueTypes use their non-boxed variants when used as the this parameter - Made ValueTypes use their non-boxed variants when used as the this parameter
- Added labeling of FieldInfo/FieldRva MetadataUsages and their respective values as comments - Added labeling of FieldInfo/FieldRva MetadataUsages and their respective values as comments
- Implemented name mangling to properly display generics and other normally-replaced characters - Implemented name mangling to properly display generics and other normally-replaced characters
* Overhauled IDA script:
- Added a progress indicator box with the current step, progress, and elapsed time
- Much faster processing compared to the old version
- Automatic disabling and re-enabling of autoanalysis
- Automatic unloading of conflicting type libraries
- Addition of custom fake string segment to show string literal contents in decompiler
- A fake xref between MethodInfo instances and their corresponding method to quickly get the correct function
### Main features ### Main features