From d0ae0cb8ea0ffd06e2c7f0fc49e5b39c77fe415f Mon Sep 17 00:00:00 2001 From: VladV Date: Mon, 6 Jun 2022 14:17:53 +0300 Subject: [PATCH] New TriPropertyExtension.Initialize method API, show errors in inspector --- Editor.Extras/Drawers/ButtonDrawer.cs | 4 +- .../Drawers/EnumToggleButtonsDrawer.cs | 4 +- Editor.Extras/Drawers/InlineEditorDrawer.cs | 4 +- Editor.Extras/Drawers/OnValueChangedDrawer.cs | 4 +- Editor.Extras/Drawers/TableListDrawer.cs | 4 +- Editor.Extras/Drawers/TitleDrawer.cs | 4 +- .../Processors/DisableIfProcessor.cs | 4 +- Editor.Extras/Processors/HideIfProcessor.cs | 4 +- Editor.Extras/Validators/InfoBoxValidator.cs | 12 +- .../Validators/ValidateInputValidator.cs | 4 +- Editor/Elements/TriPropertyElement.cs | 5 + Editor/Resolvers/ValueResolver.cs | 24 ++++ Editor/TriProperty.cs | 2 + Editor/TriPropertyDefinition.cs | 126 ++++++++---------- Editor/TriPropertyExtension.cs | 43 +++++- 15 files changed, 146 insertions(+), 102 deletions(-) diff --git a/Editor.Extras/Drawers/ButtonDrawer.cs b/Editor.Extras/Drawers/ButtonDrawer.cs index ab963ba..e315a17 100644 --- a/Editor.Extras/Drawers/ButtonDrawer.cs +++ b/Editor.Extras/Drawers/ButtonDrawer.cs @@ -14,7 +14,7 @@ namespace TriInspector.Drawers { private ValueResolver _nameResolver; - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { var isValidMethod = propertyDefinition.MemberInfo is MethodInfo mi && mi.GetParameters().Length == 0; if (!isValidMethod) @@ -28,7 +28,7 @@ namespace TriInspector.Drawers return error; } - return null; + return TriExtensionInitializationResult.Ok; } public override float GetHeight(float width, TriProperty property, TriElement next) diff --git a/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs b/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs index d9b593a..e3f14d9 100644 --- a/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs +++ b/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs @@ -14,14 +14,14 @@ namespace TriInspector.Drawers { public class EnumToggleButtonsDrawer : TriAttributeDrawer { - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { if (!propertyDefinition.FieldType.IsEnum) { return "EnumToggleButtons attribute can be used only on enums"; } - return null; + return TriExtensionInitializationResult.Ok; } public override TriElement CreateElement(TriProperty property, TriElement next) diff --git a/Editor.Extras/Drawers/InlineEditorDrawer.cs b/Editor.Extras/Drawers/InlineEditorDrawer.cs index 695cbc7..c1aced5 100644 --- a/Editor.Extras/Drawers/InlineEditorDrawer.cs +++ b/Editor.Extras/Drawers/InlineEditorDrawer.cs @@ -13,14 +13,14 @@ namespace TriInspector.Drawers { public class InlineEditorDrawer : TriAttributeDrawer { - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { if (!typeof(Object).IsAssignableFrom(propertyDefinition.FieldType)) { return "[InlineEditor] valid only on Object fields"; } - return null; + return TriExtensionInitializationResult.Ok; } public override TriElement CreateElement(TriProperty property, TriElement next) diff --git a/Editor.Extras/Drawers/OnValueChangedDrawer.cs b/Editor.Extras/Drawers/OnValueChangedDrawer.cs index 84994bb..e98aa5f 100644 --- a/Editor.Extras/Drawers/OnValueChangedDrawer.cs +++ b/Editor.Extras/Drawers/OnValueChangedDrawer.cs @@ -10,7 +10,7 @@ namespace TriInspector.Drawers { private ActionResolver _actionResolver; - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { base.Initialize(propertyDefinition); @@ -20,7 +20,7 @@ namespace TriInspector.Drawers return error; } - return null; + return TriExtensionInitializationResult.Ok; } public override TriElement CreateElement(TriProperty property, TriElement next) diff --git a/Editor.Extras/Drawers/TableListDrawer.cs b/Editor.Extras/Drawers/TableListDrawer.cs index 65db47e..ea91232 100644 --- a/Editor.Extras/Drawers/TableListDrawer.cs +++ b/Editor.Extras/Drawers/TableListDrawer.cs @@ -16,14 +16,14 @@ namespace TriInspector.Drawers { public class TableListDrawer : TriAttributeDrawer { - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { if (!propertyDefinition.IsArray) { return "[TableList] valid only on lists"; } - return null; + return TriExtensionInitializationResult.Ok; } public override TriElement CreateElement(TriProperty property, TriElement next) diff --git a/Editor.Extras/Drawers/TitleDrawer.cs b/Editor.Extras/Drawers/TitleDrawer.cs index 58ae516..bcd83a3 100644 --- a/Editor.Extras/Drawers/TitleDrawer.cs +++ b/Editor.Extras/Drawers/TitleDrawer.cs @@ -17,7 +17,7 @@ namespace TriInspector.Drawers private ValueResolver _titleResolver; - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { base.Initialize(propertyDefinition); @@ -28,7 +28,7 @@ namespace TriInspector.Drawers return error; } - return null; + return TriExtensionInitializationResult.Ok; } public override float GetHeight(float width, TriProperty property, TriElement next) diff --git a/Editor.Extras/Processors/DisableIfProcessor.cs b/Editor.Extras/Processors/DisableIfProcessor.cs index 7e38f34..65ba593 100644 --- a/Editor.Extras/Processors/DisableIfProcessor.cs +++ b/Editor.Extras/Processors/DisableIfProcessor.cs @@ -19,7 +19,7 @@ namespace TriInspector.Processors _inverse = inverse; } - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { base.Initialize(propertyDefinition); @@ -29,7 +29,7 @@ namespace TriInspector.Processors return error; } - return null; + return TriExtensionInitializationResult.Ok; } public sealed override bool IsDisabled(TriProperty property) diff --git a/Editor.Extras/Processors/HideIfProcessor.cs b/Editor.Extras/Processors/HideIfProcessor.cs index ec7abe9..454a44b 100644 --- a/Editor.Extras/Processors/HideIfProcessor.cs +++ b/Editor.Extras/Processors/HideIfProcessor.cs @@ -19,7 +19,7 @@ namespace TriInspector.Processors _inverse = inverse; } - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { base.Initialize(propertyDefinition); @@ -30,7 +30,7 @@ namespace TriInspector.Processors return error; } - return null; + return TriExtensionInitializationResult.Ok; } public sealed override bool IsHidden(TriProperty property) diff --git a/Editor.Extras/Validators/InfoBoxValidator.cs b/Editor.Extras/Validators/InfoBoxValidator.cs index dc0a166..34122cd 100644 --- a/Editor.Extras/Validators/InfoBoxValidator.cs +++ b/Editor.Extras/Validators/InfoBoxValidator.cs @@ -11,25 +11,19 @@ namespace TriInspector.Validators private ValueResolver _resolver; private ValueResolver _visibleIfResolver; - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { _resolver = ValueResolver.ResolveString(propertyDefinition, Attribute.Text); _visibleIfResolver = Attribute.VisibleIf != null ? ValueResolver.Resolve(propertyDefinition, Attribute.VisibleIf) : null; - if (_resolver.TryGetErrorString(out var error)) + if (ValueResolver.TryGetErrorString(_resolver, _visibleIfResolver, out var error)) { return error; } - if (_visibleIfResolver != null && - _visibleIfResolver.TryGetErrorString(out var error2)) - { - return error2; - } - - return null; + return TriExtensionInitializationResult.Ok; } public override TriValidationResult Validate(TriProperty property) diff --git a/Editor.Extras/Validators/ValidateInputValidator.cs b/Editor.Extras/Validators/ValidateInputValidator.cs index 1390aa8..7c4bbf5 100644 --- a/Editor.Extras/Validators/ValidateInputValidator.cs +++ b/Editor.Extras/Validators/ValidateInputValidator.cs @@ -10,7 +10,7 @@ namespace TriInspector.Validators { private ValueResolver _resolver; - public override string Initialize(TriPropertyDefinition propertyDefinition) + public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { base.Initialize(propertyDefinition); @@ -21,7 +21,7 @@ namespace TriInspector.Validators return error; } - return null; + return TriExtensionInitializationResult.Ok; } public override TriValidationResult Validate(TriProperty property) diff --git a/Editor/Elements/TriPropertyElement.cs b/Editor/Elements/TriPropertyElement.cs index 0fae7ad..112d0cf 100644 --- a/Editor/Elements/TriPropertyElement.cs +++ b/Editor/Elements/TriPropertyElement.cs @@ -19,6 +19,11 @@ namespace TriInspector.Elements { _property = property; + foreach (var error in _property.ExtensionErrors) + { + AddChild(new TriInfoBoxElement(error, TriMessageType.Error)); + } + var element = CreateElement(property, props); var drawers = property.AllDrawers; diff --git a/Editor/Resolvers/ValueResolver.cs b/Editor/Resolvers/ValueResolver.cs index cf2e98b..0b4f39e 100644 --- a/Editor/Resolvers/ValueResolver.cs +++ b/Editor/Resolvers/ValueResolver.cs @@ -35,6 +35,30 @@ namespace TriInspector.Resolvers return new ConstantValueResolver(expression); } + + public static bool TryGetErrorString([CanBeNull] ValueResolver resolver, out string error) + { + return TryGetErrorString(resolver, null, out error); + } + + public static bool TryGetErrorString(ValueResolver resolver1, ValueResolver 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 diff --git a/Editor/TriProperty.cs b/Editor/TriProperty.cs index 7ae24eb..755d898 100644 --- a/Editor/TriProperty.cs +++ b/Editor/TriProperty.cs @@ -188,6 +188,8 @@ namespace TriInspector public IReadOnlyList AllDrawers => _definition.Drawers; + internal IReadOnlyList ExtensionErrors => _definition.ExtensionErrors; + public bool HasValidators => _definition.Validators.Count != 0; public IReadOnlyList ValidationResults => diff --git a/Editor/TriPropertyDefinition.cs b/Editor/TriPropertyDefinition.cs index 5eaa1a1..46a6358 100644 --- a/Editor/TriPropertyDefinition.cs +++ b/Editor/TriPropertyDefinition.cs @@ -15,6 +15,8 @@ namespace TriInspector private readonly ValueGetterDelegate _valueGetter; [CanBeNull] private readonly ValueSetterDelegate _valueSetter; + private readonly List _extensionErrors = new List(); + private TriPropertyDefinition _arrayElementDefinitionBackingField; private IReadOnlyList _drawersBackingField; @@ -95,74 +97,20 @@ namespace TriInspector [CanBeNull] public ValueResolver CustomLabel { get; } [CanBeNull] public ValueResolver CustomTooltip { get; } - public IReadOnlyList HideProcessors + public IReadOnlyList HideProcessors => PopulateHideProcessor(); + public IReadOnlyList DisableProcessors => PopulateDisableProcessors(); + public IReadOnlyList Drawers => PopulateDrawers(); + public IReadOnlyList Validators => PopulateValidators(); + + internal IReadOnlyList ExtensionErrors { get { - if (_hideProcessorsBackingField == null) - { - _hideProcessorsBackingField = - TriDrawersUtilities.CreateHideProcessorsFor(Attributes) - .Where(CanApplyExtensionOnSelf) - .ToList(); - } - - return _hideProcessorsBackingField; - } - } - - public IReadOnlyList DisableProcessors - { - get - { - if (_disableProcessorsBackingField == null) - { - _disableProcessorsBackingField = - TriDrawersUtilities.CreateDisableProcessorsFor(Attributes) - .Where(CanApplyExtensionOnSelf) - .ToList(); - } - - return _disableProcessorsBackingField; - } - } - - public IReadOnlyList Drawers - { - get - { - if (_drawersBackingField == null) - { - _drawersBackingField = Enumerable.Empty() - .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 Validators - { - get - { - if (_validatorsBackingField == null) - { - _validatorsBackingField = Enumerable.Empty() - .Concat(TriDrawersUtilities.CreateValueValidatorsFor(FieldType)) - .Concat(TriDrawersUtilities.CreateAttributeValidatorsFor(Attributes)) - .Where(CanApplyExtensionOnSelf) - .ToList(); - } - - return _validatorsBackingField; + PopulateHideProcessor(); + PopulateDisableProcessors(); + PopulateDrawers(); + PopulateValidators(); + return _extensionErrors; } } @@ -217,6 +165,43 @@ namespace TriInspector } } + private IReadOnlyList PopulateHideProcessor() + { + return _hideProcessorsBackingField ??= TriDrawersUtilities.CreateHideProcessorsFor(Attributes) + .Where(CanApplyExtensionOnSelf) + .ToList(); + } + + private IReadOnlyList PopulateDisableProcessors() + { + return _disableProcessorsBackingField ??= TriDrawersUtilities.CreateDisableProcessorsFor(Attributes) + .Where(CanApplyExtensionOnSelf) + .ToList(); + } + + private IReadOnlyList PopulateValidators() + { + return _validatorsBackingField ??= Enumerable.Empty() + .Concat(TriDrawersUtilities.CreateValueValidatorsFor(FieldType)) + .Concat(TriDrawersUtilities.CreateAttributeValidatorsFor(Attributes)) + .Where(CanApplyExtensionOnSelf) + .ToList(); + } + + private IReadOnlyList PopulateDrawers() + { + return _drawersBackingField ??= Enumerable.Empty() + .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) { return (self, targetIndex) => @@ -287,16 +272,13 @@ namespace TriInspector } } - var error = propertyExtension.Initialize(this); - if (error != null) + var result = propertyExtension.Initialize(this); + if (result.IsError) { - var message = $"Extension {propertyExtension.GetType()} cannot be applied " + - $"on property '{MemberInfo?.DeclaringType}.{Name}': {error}"; - Debug.LogError(message); - return false; + _extensionErrors.Add(result.ErrorMessage); } - return true; + return result.ShouldApply; } public delegate object ValueGetterDelegate(TriProperty self, int targetIndex); diff --git a/Editor/TriPropertyExtension.cs b/Editor/TriPropertyExtension.cs index d3f984f..b6a7f5b 100644 --- a/Editor/TriPropertyExtension.cs +++ b/Editor/TriPropertyExtension.cs @@ -1,4 +1,5 @@ -using JetBrains.Annotations; +using System; +using JetBrains.Annotations; namespace TriInspector { @@ -7,9 +8,45 @@ namespace TriInspector public bool? ApplyOnArrayElement { get; internal set; } [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); } } } \ No newline at end of file