2021-04-16 21:07:45 +10:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.EventSystems;
|
|
|
|
|
using UnityExplorer.Core.Runtime;
|
|
|
|
|
|
|
|
|
|
namespace UnityExplorer.UI.Utility
|
|
|
|
|
{
|
|
|
|
|
public static class ToStringUtility
|
|
|
|
|
{
|
|
|
|
|
internal static Dictionary<Type, MethodInfo> toStringMethods = new Dictionary<Type, MethodInfo>();
|
|
|
|
|
internal static Dictionary<Type, MethodInfo> toStringFormattedMethods = new Dictionary<Type, MethodInfo>();
|
|
|
|
|
|
2021-04-25 21:21:05 +10:00
|
|
|
|
// string allocs
|
|
|
|
|
private static readonly StringBuilder _stringBuilder = new StringBuilder(16384);
|
|
|
|
|
private const string unknownString = "<unknown>";
|
|
|
|
|
private const string nullString = "<color=grey>[null]</color>";
|
|
|
|
|
private const string destroyedString = "<color=red>[Destroyed]</color>";
|
|
|
|
|
|
2021-04-24 04:03:33 +10:00
|
|
|
|
public static string ToString(object value, Type fallbackType, bool includeNamespace = true, bool includeName = true)
|
2021-04-16 21:07:45 +10:00
|
|
|
|
{
|
|
|
|
|
if (value == null && fallbackType == null)
|
2021-04-25 21:21:05 +10:00
|
|
|
|
return unknownString;
|
2021-04-16 21:07:45 +10:00
|
|
|
|
|
2021-04-24 04:03:33 +10:00
|
|
|
|
Type type = value?.GetActualType() ?? fallbackType;
|
2021-04-16 21:07:45 +10:00
|
|
|
|
|
2021-04-25 21:21:05 +10:00
|
|
|
|
// todo SB this too
|
|
|
|
|
string richType = SignatureHighlighter.ParseFullSyntax(type, includeNamespace);
|
2021-04-16 21:07:45 +10:00
|
|
|
|
|
|
|
|
|
if (!includeName)
|
|
|
|
|
return richType;
|
|
|
|
|
|
2021-04-25 21:21:05 +10:00
|
|
|
|
_stringBuilder.Clear();
|
|
|
|
|
|
2021-04-16 21:07:45 +10:00
|
|
|
|
if (value.IsNullOrDestroyed())
|
2021-04-24 04:03:33 +10:00
|
|
|
|
{
|
|
|
|
|
if (value == null)
|
2021-04-25 21:21:05 +10:00
|
|
|
|
{
|
|
|
|
|
_stringBuilder.Append(nullString);
|
|
|
|
|
AppendRichType(_stringBuilder, richType);
|
|
|
|
|
return _stringBuilder.ToString();
|
|
|
|
|
}
|
|
|
|
|
else // destroyed unity object
|
|
|
|
|
{
|
|
|
|
|
_stringBuilder.Append(destroyedString);
|
|
|
|
|
AppendRichType(_stringBuilder, richType);
|
|
|
|
|
return _stringBuilder.ToString();
|
|
|
|
|
}
|
2021-04-24 04:03:33 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-25 21:21:05 +10:00
|
|
|
|
if (value is UnityEngine.Object obj)
|
|
|
|
|
{
|
|
|
|
|
_stringBuilder.Append(obj.name);
|
|
|
|
|
AppendRichType(_stringBuilder, richType);
|
2021-04-16 21:07:45 +10:00
|
|
|
|
}
|
2021-04-25 21:21:05 +10:00
|
|
|
|
else
|
2021-04-16 21:07:45 +10:00
|
|
|
|
{
|
|
|
|
|
if (!toStringMethods.ContainsKey(type))
|
|
|
|
|
{
|
|
|
|
|
var toStringMethod = type.GetMethod("ToString", new Type[0]);
|
|
|
|
|
var formatMethod = type.GetMethod("ToString", new Type[] { typeof(string) });
|
|
|
|
|
|
|
|
|
|
if (formatMethod != null)
|
|
|
|
|
{
|
|
|
|
|
try { formatMethod.Invoke(value, new object[] { "F3" }); }
|
|
|
|
|
catch { formatMethod = null; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toStringMethods.Add(type, toStringMethod);
|
|
|
|
|
toStringFormattedMethods.Add(type, formatMethod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var f3Method = toStringFormattedMethods[type];
|
|
|
|
|
var stdMethod = toStringMethods[type];
|
|
|
|
|
|
2021-04-24 04:03:33 +10:00
|
|
|
|
value = value.TryCast(type);
|
|
|
|
|
|
2021-04-16 21:07:45 +10:00
|
|
|
|
string toString;
|
|
|
|
|
if (f3Method != null)
|
|
|
|
|
toString = (string)f3Method.Invoke(value, new object[] { "F3" });
|
|
|
|
|
else
|
|
|
|
|
toString = (string)stdMethod.Invoke(value, new object[0]);
|
|
|
|
|
|
2021-04-25 21:21:05 +10:00
|
|
|
|
if (toString == type.FullName || toString == $"Il2Cpp{type.FullName}")
|
2021-04-16 21:07:45 +10:00
|
|
|
|
{
|
2021-04-25 21:21:05 +10:00
|
|
|
|
// the ToString was just the default object.ToString(), use our
|
|
|
|
|
// syntax highlighted type name instead.
|
|
|
|
|
_stringBuilder.Append(richType);
|
2021-04-16 21:07:45 +10:00
|
|
|
|
}
|
2021-04-25 21:21:05 +10:00
|
|
|
|
else // the ToString contains some actual implementation, use that value.
|
2021-04-16 21:07:45 +10:00
|
|
|
|
{
|
|
|
|
|
if (toString.Length > 200)
|
2021-04-25 21:21:05 +10:00
|
|
|
|
_stringBuilder.Append(toString.Substring(0, 200));
|
2021-04-16 21:07:45 +10:00
|
|
|
|
else
|
2021-04-25 21:21:05 +10:00
|
|
|
|
_stringBuilder.Append(toString);
|
|
|
|
|
|
|
|
|
|
AppendRichType(_stringBuilder, richType);
|
2021-04-16 21:07:45 +10:00
|
|
|
|
}
|
2021-04-25 21:21:05 +10:00
|
|
|
|
|
|
|
|
|
////string toString;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
//toString = toString ?? "";
|
|
|
|
|
//
|
|
|
|
|
//string typeName = type.FullName;
|
|
|
|
|
//if (typeName.StartsWith("Il2CppSystem."))
|
|
|
|
|
// typeName = typeName.Substring(6, typeName.Length - 6);
|
|
|
|
|
//
|
|
|
|
|
//toString = ReflectionProvider.Instance.ProcessTypeFullNameInString(type, toString, ref typeName);
|
|
|
|
|
//
|
|
|
|
|
//// If the ToString is just the type name, use our syntax highlighted type name instead.
|
|
|
|
|
//if (toString == typeName)
|
|
|
|
|
//{
|
|
|
|
|
// label = richType;
|
|
|
|
|
//}
|
|
|
|
|
//else // Otherwise, parse the result and put our highlighted name in.
|
|
|
|
|
//{
|
|
|
|
|
// if (toString.Length > 200)
|
|
|
|
|
// toString = toString.Substring(0, 200) + "...";
|
|
|
|
|
//
|
|
|
|
|
// label = toString;
|
|
|
|
|
//
|
|
|
|
|
// var unityType = $"({type.FullName})";
|
|
|
|
|
// if (value is UnityEngine.Object && label.Contains(unityType))
|
|
|
|
|
// label = label.Replace(unityType, $"({richType})");
|
|
|
|
|
// else
|
|
|
|
|
// label += $" ({richType})";
|
|
|
|
|
//}
|
2021-04-16 21:07:45 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-25 21:21:05 +10:00
|
|
|
|
return _stringBuilder.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Just a little optimization, append chars directly instead of allocating every time
|
|
|
|
|
// we want to do this.
|
|
|
|
|
private static void AppendRichType(StringBuilder sb, string richType)
|
|
|
|
|
{
|
|
|
|
|
sb.Append(' ');
|
|
|
|
|
sb.Append('(');
|
|
|
|
|
sb.Append(richType);
|
|
|
|
|
sb.Append(')');
|
2021-04-16 21:07:45 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|