New TriPropertyExtension.Initialize method API, show errors in inspector

This commit is contained in:
VladV 2022-06-06 14:17:53 +03:00
parent 383815a216
commit d0ae0cb8ea
15 changed files with 146 additions and 102 deletions

View File

@ -14,7 +14,7 @@ namespace TriInspector.Drawers
{ {
private ValueResolver<string> _nameResolver; private ValueResolver<string> _nameResolver;
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
var isValidMethod = propertyDefinition.MemberInfo is MethodInfo mi && mi.GetParameters().Length == 0; var isValidMethod = propertyDefinition.MemberInfo is MethodInfo mi && mi.GetParameters().Length == 0;
if (!isValidMethod) if (!isValidMethod)
@ -28,7 +28,7 @@ namespace TriInspector.Drawers
return error; return error;
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public override float GetHeight(float width, TriProperty property, TriElement next) public override float GetHeight(float width, TriProperty property, TriElement next)

View File

@ -14,14 +14,14 @@ namespace TriInspector.Drawers
{ {
public class EnumToggleButtonsDrawer : TriAttributeDrawer<EnumToggleButtonsAttribute> public class EnumToggleButtonsDrawer : TriAttributeDrawer<EnumToggleButtonsAttribute>
{ {
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
if (!propertyDefinition.FieldType.IsEnum) if (!propertyDefinition.FieldType.IsEnum)
{ {
return "EnumToggleButtons attribute can be used only on enums"; return "EnumToggleButtons attribute can be used only on enums";
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public override TriElement CreateElement(TriProperty property, TriElement next) public override TriElement CreateElement(TriProperty property, TriElement next)

View File

@ -13,14 +13,14 @@ namespace TriInspector.Drawers
{ {
public class InlineEditorDrawer : TriAttributeDrawer<InlineEditorAttribute> public class InlineEditorDrawer : TriAttributeDrawer<InlineEditorAttribute>
{ {
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
if (!typeof(Object).IsAssignableFrom(propertyDefinition.FieldType)) if (!typeof(Object).IsAssignableFrom(propertyDefinition.FieldType))
{ {
return "[InlineEditor] valid only on Object fields"; return "[InlineEditor] valid only on Object fields";
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public override TriElement CreateElement(TriProperty property, TriElement next) public override TriElement CreateElement(TriProperty property, TriElement next)

View File

@ -10,7 +10,7 @@ namespace TriInspector.Drawers
{ {
private ActionResolver _actionResolver; private ActionResolver _actionResolver;
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
base.Initialize(propertyDefinition); base.Initialize(propertyDefinition);
@ -20,7 +20,7 @@ namespace TriInspector.Drawers
return error; return error;
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public override TriElement CreateElement(TriProperty property, TriElement next) public override TriElement CreateElement(TriProperty property, TriElement next)

View File

@ -16,14 +16,14 @@ namespace TriInspector.Drawers
{ {
public class TableListDrawer : TriAttributeDrawer<TableListAttribute> public class TableListDrawer : TriAttributeDrawer<TableListAttribute>
{ {
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
if (!propertyDefinition.IsArray) if (!propertyDefinition.IsArray)
{ {
return "[TableList] valid only on lists"; return "[TableList] valid only on lists";
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public override TriElement CreateElement(TriProperty property, TriElement next) public override TriElement CreateElement(TriProperty property, TriElement next)

View File

@ -17,7 +17,7 @@ namespace TriInspector.Drawers
private ValueResolver<string> _titleResolver; private ValueResolver<string> _titleResolver;
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
base.Initialize(propertyDefinition); base.Initialize(propertyDefinition);
@ -28,7 +28,7 @@ namespace TriInspector.Drawers
return error; return error;
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public override float GetHeight(float width, TriProperty property, TriElement next) public override float GetHeight(float width, TriProperty property, TriElement next)

View File

@ -19,7 +19,7 @@ namespace TriInspector.Processors
_inverse = inverse; _inverse = inverse;
} }
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
base.Initialize(propertyDefinition); base.Initialize(propertyDefinition);
@ -29,7 +29,7 @@ namespace TriInspector.Processors
return error; return error;
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public sealed override bool IsDisabled(TriProperty property) public sealed override bool IsDisabled(TriProperty property)

View File

@ -19,7 +19,7 @@ namespace TriInspector.Processors
_inverse = inverse; _inverse = inverse;
} }
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
base.Initialize(propertyDefinition); base.Initialize(propertyDefinition);
@ -30,7 +30,7 @@ namespace TriInspector.Processors
return error; return error;
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public sealed override bool IsHidden(TriProperty property) public sealed override bool IsHidden(TriProperty property)

View File

@ -11,25 +11,19 @@ namespace TriInspector.Validators
private ValueResolver<string> _resolver; private ValueResolver<string> _resolver;
private ValueResolver<bool> _visibleIfResolver; private ValueResolver<bool> _visibleIfResolver;
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
_resolver = ValueResolver.ResolveString(propertyDefinition, Attribute.Text); _resolver = ValueResolver.ResolveString(propertyDefinition, Attribute.Text);
_visibleIfResolver = Attribute.VisibleIf != null _visibleIfResolver = Attribute.VisibleIf != null
? ValueResolver.Resolve<bool>(propertyDefinition, Attribute.VisibleIf) ? ValueResolver.Resolve<bool>(propertyDefinition, Attribute.VisibleIf)
: null; : null;
if (_resolver.TryGetErrorString(out var error)) if (ValueResolver.TryGetErrorString(_resolver, _visibleIfResolver, out var error))
{ {
return error; return error;
} }
if (_visibleIfResolver != null && return TriExtensionInitializationResult.Ok;
_visibleIfResolver.TryGetErrorString(out var error2))
{
return error2;
}
return null;
} }
public override TriValidationResult Validate(TriProperty property) public override TriValidationResult Validate(TriProperty property)

View File

@ -10,7 +10,7 @@ namespace TriInspector.Validators
{ {
private ValueResolver<TriValidationResult> _resolver; private ValueResolver<TriValidationResult> _resolver;
public override string Initialize(TriPropertyDefinition propertyDefinition) public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
base.Initialize(propertyDefinition); base.Initialize(propertyDefinition);
@ -21,7 +21,7 @@ namespace TriInspector.Validators
return error; return error;
} }
return null; return TriExtensionInitializationResult.Ok;
} }
public override TriValidationResult Validate(TriProperty property) public override TriValidationResult Validate(TriProperty property)

View File

@ -19,6 +19,11 @@ namespace TriInspector.Elements
{ {
_property = property; _property = property;
foreach (var error in _property.ExtensionErrors)
{
AddChild(new TriInfoBoxElement(error, TriMessageType.Error));
}
var element = CreateElement(property, props); var element = CreateElement(property, props);
var drawers = property.AllDrawers; var drawers = property.AllDrawers;

View File

@ -35,6 +35,30 @@ namespace TriInspector.Resolvers
return new ConstantValueResolver<string>(expression); return new ConstantValueResolver<string>(expression);
} }
public static bool TryGetErrorString<T>([CanBeNull] ValueResolver<T> resolver, out string error)
{
return TryGetErrorString<T, T>(resolver, null, out error);
}
public static bool TryGetErrorString<T1, T2>(ValueResolver<T1> resolver1, ValueResolver<T2> resolver2,
out string error)
{
if (resolver1 != null && resolver1.TryGetErrorString(out var error1))
{
error = error1;
return true;
}
if (resolver2 != null && resolver2.TryGetErrorString(out var error2))
{
error = error2;
return true;
}
error = null;
return false;
}
} }
public abstract class ValueResolver<T> public abstract class ValueResolver<T>

View File

@ -188,6 +188,8 @@ namespace TriInspector
public IReadOnlyList<TriCustomDrawer> AllDrawers => _definition.Drawers; public IReadOnlyList<TriCustomDrawer> AllDrawers => _definition.Drawers;
internal IReadOnlyList<string> ExtensionErrors => _definition.ExtensionErrors;
public bool HasValidators => _definition.Validators.Count != 0; public bool HasValidators => _definition.Validators.Count != 0;
public IReadOnlyList<TriValidationResult> ValidationResults => public IReadOnlyList<TriValidationResult> ValidationResults =>

View File

@ -15,6 +15,8 @@ namespace TriInspector
private readonly ValueGetterDelegate _valueGetter; private readonly ValueGetterDelegate _valueGetter;
[CanBeNull] private readonly ValueSetterDelegate _valueSetter; [CanBeNull] private readonly ValueSetterDelegate _valueSetter;
private readonly List<string> _extensionErrors = new List<string>();
private TriPropertyDefinition _arrayElementDefinitionBackingField; private TriPropertyDefinition _arrayElementDefinitionBackingField;
private IReadOnlyList<TriCustomDrawer> _drawersBackingField; private IReadOnlyList<TriCustomDrawer> _drawersBackingField;
@ -95,74 +97,20 @@ namespace TriInspector
[CanBeNull] public ValueResolver<string> CustomLabel { get; } [CanBeNull] public ValueResolver<string> CustomLabel { get; }
[CanBeNull] public ValueResolver<string> CustomTooltip { get; } [CanBeNull] public ValueResolver<string> CustomTooltip { get; }
public IReadOnlyList<TriPropertyHideProcessor> HideProcessors public IReadOnlyList<TriPropertyHideProcessor> HideProcessors => PopulateHideProcessor();
public IReadOnlyList<TriPropertyDisableProcessor> DisableProcessors => PopulateDisableProcessors();
public IReadOnlyList<TriCustomDrawer> Drawers => PopulateDrawers();
public IReadOnlyList<TriValidator> Validators => PopulateValidators();
internal IReadOnlyList<string> ExtensionErrors
{ {
get get
{ {
if (_hideProcessorsBackingField == null) PopulateHideProcessor();
{ PopulateDisableProcessors();
_hideProcessorsBackingField = PopulateDrawers();
TriDrawersUtilities.CreateHideProcessorsFor(Attributes) PopulateValidators();
.Where(CanApplyExtensionOnSelf) return _extensionErrors;
.ToList();
}
return _hideProcessorsBackingField;
}
}
public IReadOnlyList<TriPropertyDisableProcessor> DisableProcessors
{
get
{
if (_disableProcessorsBackingField == null)
{
_disableProcessorsBackingField =
TriDrawersUtilities.CreateDisableProcessorsFor(Attributes)
.Where(CanApplyExtensionOnSelf)
.ToList();
}
return _disableProcessorsBackingField;
}
}
public IReadOnlyList<TriCustomDrawer> Drawers
{
get
{
if (_drawersBackingField == null)
{
_drawersBackingField = Enumerable.Empty<TriCustomDrawer>()
.Concat(TriDrawersUtilities.CreateValueDrawersFor(FieldType))
.Concat(TriDrawersUtilities.CreateAttributeDrawersFor(Attributes))
.Concat(new[]
{
new ValidatorsDrawer {Order = TriDrawerOrder.Validator,},
})
.Where(CanApplyExtensionOnSelf)
.OrderBy(it => it.Order)
.ToList();
}
return _drawersBackingField;
}
}
public IReadOnlyList<TriValidator> Validators
{
get
{
if (_validatorsBackingField == null)
{
_validatorsBackingField = Enumerable.Empty<TriValidator>()
.Concat(TriDrawersUtilities.CreateValueValidatorsFor(FieldType))
.Concat(TriDrawersUtilities.CreateAttributeValidatorsFor(Attributes))
.Where(CanApplyExtensionOnSelf)
.ToList();
}
return _validatorsBackingField;
} }
} }
@ -217,6 +165,43 @@ namespace TriInspector
} }
} }
private IReadOnlyList<TriPropertyHideProcessor> PopulateHideProcessor()
{
return _hideProcessorsBackingField ??= TriDrawersUtilities.CreateHideProcessorsFor(Attributes)
.Where(CanApplyExtensionOnSelf)
.ToList();
}
private IReadOnlyList<TriPropertyDisableProcessor> PopulateDisableProcessors()
{
return _disableProcessorsBackingField ??= TriDrawersUtilities.CreateDisableProcessorsFor(Attributes)
.Where(CanApplyExtensionOnSelf)
.ToList();
}
private IReadOnlyList<TriValidator> PopulateValidators()
{
return _validatorsBackingField ??= Enumerable.Empty<TriValidator>()
.Concat(TriDrawersUtilities.CreateValueValidatorsFor(FieldType))
.Concat(TriDrawersUtilities.CreateAttributeValidatorsFor(Attributes))
.Where(CanApplyExtensionOnSelf)
.ToList();
}
private IReadOnlyList<TriCustomDrawer> PopulateDrawers()
{
return _drawersBackingField ??= Enumerable.Empty<TriCustomDrawer>()
.Concat(TriDrawersUtilities.CreateValueDrawersFor(FieldType))
.Concat(TriDrawersUtilities.CreateAttributeDrawersFor(Attributes))
.Concat(new[]
{
new ValidatorsDrawer {Order = TriDrawerOrder.Validator,},
})
.Where(CanApplyExtensionOnSelf)
.OrderBy(it => it.Order)
.ToList();
}
private static ValueGetterDelegate MakeGetter(FieldInfo fi) private static ValueGetterDelegate MakeGetter(FieldInfo fi)
{ {
return (self, targetIndex) => return (self, targetIndex) =>
@ -287,16 +272,13 @@ namespace TriInspector
} }
} }
var error = propertyExtension.Initialize(this); var result = propertyExtension.Initialize(this);
if (error != null) if (result.IsError)
{ {
var message = $"Extension {propertyExtension.GetType()} cannot be applied " + _extensionErrors.Add(result.ErrorMessage);
$"on property '{MemberInfo?.DeclaringType}.{Name}': {error}";
Debug.LogError(message);
return false;
} }
return true; return result.ShouldApply;
} }
public delegate object ValueGetterDelegate(TriProperty self, int targetIndex); public delegate object ValueGetterDelegate(TriProperty self, int targetIndex);

View File

@ -1,4 +1,5 @@
using JetBrains.Annotations; using System;
using JetBrains.Annotations;
namespace TriInspector namespace TriInspector
{ {
@ -7,9 +8,45 @@ namespace TriInspector
public bool? ApplyOnArrayElement { get; internal set; } public bool? ApplyOnArrayElement { get; internal set; }
[PublicAPI] [PublicAPI]
public virtual string Initialize(TriPropertyDefinition propertyDefinition) public virtual TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition)
{ {
return null; return TriExtensionInitializationResult.Ok;
}
}
public readonly struct TriExtensionInitializationResult
{
public TriExtensionInitializationResult(bool shouldApply, string errorMessage)
{
ShouldApply = shouldApply;
ErrorMessage = errorMessage;
}
public bool ShouldApply { get; }
public string ErrorMessage { get; }
public bool IsError => ErrorMessage != null;
[PublicAPI]
public static TriExtensionInitializationResult Ok => new TriExtensionInitializationResult(true, null);
[PublicAPI]
public static TriExtensionInitializationResult Skip => new TriExtensionInitializationResult(false, null);
[PublicAPI]
public static TriExtensionInitializationResult Error([NotNull] string errorMessage)
{
if (errorMessage == null)
{
throw new ArgumentNullException(nameof(errorMessage));
}
return new TriExtensionInitializationResult(false, errorMessage);
}
[PublicAPI]
public static implicit operator TriExtensionInitializationResult(string errorMessage)
{
return Error(errorMessage);
} }
} }
} }