Made ParseUtility helper to simplify and improve parsing of various input types

This commit is contained in:
Sinai committed 2021-05-09 01:25:26 +10:00
1 parent c828d9b642
commit c04a864b74
12 files changed
+512 -106

No files matched your search

+4 -4
View File
@@ -171,7 +171,7 @@ namespace UnityExplorer.UI.CacheObject
#region Cache Member Util
public static bool CanProcessArgs(ParameterInfo[] parameters)
public static bool CanParseArgs(ParameterInfo[] parameters)
{
foreach (var param in parameters)
{
@@ -180,7 +180,7 @@ namespace UnityExplorer.UI.CacheObject
if (pType.IsByRef && pType.HasElementType)
pType = pType.GetElementType();
if (pType != null && (pType.IsPrimitive || pType == typeof(string)))
if (pType != null && ParseUtility.CanParse(pType))
continue;
else
return false;
@@ -260,7 +260,7 @@ namespace UnityExplorer.UI.CacheObject
return;
var args = mi.GetParameters();
if (!CanProcessArgs(args))
if (!CanParseArgs(args))
return;
sig += AppendArgsToSig(args);
@@ -277,7 +277,7 @@ namespace UnityExplorer.UI.CacheObject
var pi = member as PropertyInfo;
var args = pi.GetIndexParameters();
if (!CanProcessArgs(args))
if (!CanParseArgs(args))
return;
if (!pi.CanRead && pi.CanWrite)
+37 -29
View File
@@ -39,6 +39,9 @@ namespace UnityExplorer.UI.CacheObject
public Type FallbackType { get; protected set; }
public bool LastValueWasNull { get; private set; }
public ValueState State = ValueState.NotEvaluated;
public Type LastValueType;
public InteractiveValue IValue { get; private set; }
public Type CurrentIValueType { get; private set; }
public bool SubContentShowWanted { get; private set; }
@@ -58,12 +61,6 @@ namespace UnityExplorer.UI.CacheObject
this.ValueLabelText = GetValueLabel();
}
// internals
// private static readonly Dictionary<string, MethodInfo> numberParseMethods = new Dictionary<string, MethodInfo>();
public ValueState State = ValueState.NotEvaluated;
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
public virtual void ReleasePooledObjects()
@@ -127,6 +124,7 @@ namespace UnityExplorer.UI.CacheObject
if (HadException)
{
LastValueWasNull = true;
LastValueType = FallbackType;
State = ValueState.Exception;
}
else if (Value.IsNullOrDestroyed())
@@ -158,6 +156,10 @@ namespace UnityExplorer.UI.CacheObject
public ValueState GetStateForType(Type type)
{
if (LastValueType == type)
return State;
LastValueType = type;
if (type == typeof(bool))
return ValueState.Boolean;
else if (type.IsPrimitive || type == typeof(decimal))
@@ -184,17 +186,24 @@ namespace UnityExplorer.UI.CacheObject
switch (State)
{
case ValueState.NotEvaluated:
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
case ValueState.Exception:
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
// bool and number dont want the label for the value at all
case ValueState.Boolean:
case ValueState.Number:
return null;
case ValueState.NotEvaluated:
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
case ValueState.Exception:
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
// and valuestruct also doesnt want it if we can parse it
case ValueState.ValueStruct:
if (ParseUtility.CanParse(LastValueType))
return null;
break;
// string wants it trimmed to max 200 chars
case ValueState.String:
if (!LastValueWasNull)
{
@@ -204,7 +213,8 @@ namespace UnityExplorer.UI.CacheObject
return $"\"{s}\"";
}
break;
// try to prefix the count of the collection for lists and dicts
case ValueState.Collection:
if (!LastValueWasNull)
{
@@ -256,7 +266,6 @@ namespace UnityExplorer.UI.CacheObject
switch (State)
{
case ValueState.Exception:
//case ValueState.NullValue:
SetValueState(cell, ValueStateArgs.Default);
break;
case ValueState.Boolean:
@@ -274,10 +283,15 @@ namespace UnityExplorer.UI.CacheObject
case ValueState.Enum:
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: CanWrite));
break;
case ValueState.Color:
case ValueState.ValueStruct:
if (ParseUtility.CanParse(LastValueType))
SetValueState(cell, new ValueStateArgs(false, false, null, true, false, true, CanWrite, true, true));
else
SetValueState(cell, new ValueStateArgs(true, inspectActive: true, subContentButtonActive: true));
break;
case ValueState.Collection:
case ValueState.Dictionary:
case ValueState.ValueStruct:
case ValueState.Color:
SetValueState(cell, new ValueStateArgs(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
break;
case ValueState.Unsupported:
@@ -303,7 +317,7 @@ namespace UnityExplorer.UI.CacheObject
// Type label (for primitives)
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
if (args.typeLabelActive)
cell.TypeLabel.text = SignatureHighlighter.Parse(Value.GetActualType(), false);
cell.TypeLabel.text = SignatureHighlighter.Parse(LastValueType, false);
// toggle for bools
cell.Toggle.gameObject.SetActive(args.toggleActive);
@@ -318,7 +332,7 @@ namespace UnityExplorer.UI.CacheObject
cell.InputField.UIRoot.SetActive(args.inputActive);
if (args.inputActive)
{
cell.InputField.Text = Value.ToString();
cell.InputField.Text = ParseUtility.ToStringForInput(Value, LastValueType);
cell.InputField.InputField.readOnly = !CanWrite;
}
@@ -342,21 +356,15 @@ namespace UnityExplorer.UI.CacheObject
SetUserValue(this.CellView.Toggle.isOn);
else
{
try
if (ParseUtility.TryParse(CellView.InputField.Text, LastValueType, out object value, out Exception ex))
{
var type = Value.GetType();
var val = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs)
.Invoke(null, new object[] { CellView.InputField.Text });
SetUserValue(val);
SetUserValue(value);
}
catch (ArgumentException) { } // ignore bad user input
catch (FormatException) { }
catch (OverflowException) { }
catch (Exception ex)
else
{
ExplorerCore.LogWarning("CacheObjectBase OnCellApplyClicked (number): " + ex.ToString());
ExplorerCore.LogWarning("Unable to parse input!");
if (ex != null)
ExplorerCore.Log(ex.ReflectionExToString());
}
}
+8 -6
View File
@@ -155,16 +155,18 @@ namespace UnityExplorer.UI.CacheObject.Views
InputField = UIFactory.CreateInputField(rightHoriGroup, "InputField", "...");
UIFactory.SetLayoutElement(InputField.UIRoot, minWidth: 150, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
// Inspect and apply buttons
// Apply
InspectButton = UIFactory.CreateButton(rightHoriGroup, "InspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(InspectButton.Button.gameObject, minWidth: 60, flexibleWidth: 0, minHeight: 25);
InspectButton.OnClick += InspectClicked;
ApplyButton = UIFactory.CreateButton(rightHoriGroup, "ApplyButton", "Apply", new Color(0.15f, 0.15f, 0.15f));
ApplyButton = UIFactory.CreateButton(rightHoriGroup, "ApplyButton", "Apply", new Color(0.15f, 0.19f, 0.15f));
UIFactory.SetLayoutElement(ApplyButton.Button.gameObject, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ApplyButton.OnClick += ApplyClicked;
// Inspect
InspectButton = UIFactory.CreateButton(rightHoriGroup, "InspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(InspectButton.Button.gameObject, minWidth: 70, flexibleWidth: 0, minHeight: 25);
InspectButton.OnClick += InspectClicked;
// Main value label
ValueLabel = UIFactory.CreateLabel(rightHoriGroup, "ValueLabel", "Value goes here", TextAnchor.MiddleLeft);
+15 -10
View File
@@ -33,7 +33,7 @@ namespace UnityExplorer.UI.CacheObject.Views
private readonly List<Text> genericArgLabels = new List<Text>();
private readonly List<TypeCompleter> genericAutocompleters = new List<TypeCompleter>();
private readonly List<InputFieldRef> inputFieldCache = new List<InputFieldRef>();
private readonly List<InputFieldRef> inputFields = new List<InputFieldRef>();
public void OnBorrowedFromPool(CacheMember owner)
{
@@ -52,7 +52,7 @@ namespace UnityExplorer.UI.CacheObject.Views
public void OnReturnToPool()
{
foreach (var input in inputFieldCache)
foreach (var input in inputFields)
input.Text = "";
this.Owner = null;
@@ -99,15 +99,11 @@ namespace UnityExplorer.UI.CacheObject.Views
continue;
}
try
if (!ParseUtility.TryParse(input, type, out outArgs[i], out Exception ex))
{
var parse = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs);
outArgs[i] = parse.Invoke(null, new object[] { input });
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name}), {ex.GetType().Name}: {ex.Message}");
outArgs[i] = null;
ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name})" +
$"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}");
}
}
@@ -199,6 +195,15 @@ namespace UnityExplorer.UI.CacheObject.Views
argRows[i].SetActive(true);
argLabels[i].text = $"{SignatureHighlighter.Parse(arg.ParameterType, false)} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>";
if (arg.ParameterType == typeof(string))
inputFields[i].PlaceholderText.text = "";
else
{
var elemType = arg.ParameterType;
if (elemType.IsByRef)
elemType = elemType.GetElementType();
inputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}";
}
}
}
@@ -228,7 +233,7 @@ namespace UnityExplorer.UI.CacheObject.Views
inputField.InputField.lineType = InputField.LineType.MultiLineNewline;
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
inputField.OnValueChanged += (string val) => { inputArray[index] = val; };
inputFieldCache.Add(inputField);
inputFields.Add(inputField);
if (autocomplete)
genericAutocompleters.Add(new TypeCompleter(null, inputField));