Editor/TypeSelectAttributeExtensions.cs
using ExtendedEditor.Attributes;
using Sandbox;
using System;
using System.Linq;
using System.Reflection;

namespace ExtendedEditor;

public static class TypeSelectAttributeExtensions
{
    extension(TypeSelectAttribute attribute)
    {
        public MethodInfo? FindValidatorMethod(SerializedProperty property, out object? target)
        {
            if(property.IsMultipleValues)
                throw new InvalidOperationException("Property targeting multiple values is not supported.");

            target = null;
            if(attribute.ValidatorName is null)
                return null;

            var parent = property.Parent;
            if(parent is null)
                return null;

            Type? parentType = TypeLibrary.GetType(property.Parent.TypeName)?.TargetType;

            var parentProperty = parent.ParentProperty;
            target = parentProperty?.GetValue<object>() ?? parent.Targets.FirstOrDefault();

            if(parentType is null)
            {
                if(parentProperty is not null)
                    parentType = parentProperty.IsNullable ? parentProperty.NullableType : parentProperty.PropertyType;
            }

            parentType ??= target?.GetType();

            if(parentType is null)
                return null;

            var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy;
            if(target is not null)
                flags |= BindingFlags.Instance;

            var method = parentType.GetMethods(flags).FirstOrDefault(x =>
                    x.Name == attribute.ValidatorName &&
                    x.GetParameters().Length == 1 &&
                    x.GetParameters()[0].ParameterType == typeof(Type) &&
                    x.ReturnType == typeof(bool));

            if(method?.IsStatic ?? true)
                target = null;

            return method;
        }

        public void FindAndAppendValidatorMethod(SerializedProperty serializedProperty)
        {
            var validatorMethod = attribute.FindValidatorMethod(serializedProperty, out var target);
            if(validatorMethod is null)
            {
                attribute.ValidatorName = null;
                return;
            }

            var oldValidator = attribute.Validator;
            attribute.Validator = t =>
            {
                if(!(oldValidator?.Invoke(t) ?? true))
                    return false;

                return (bool)validatorMethod?.Invoke(target, [t])!;
            };

            attribute.ValidatorName = null;
        }
    }
}