<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using Signum.Utilities;
using Signum.Utilities.Reflection;
using System.Reflection;
using System.Linq.Expressions;
using Signum.Utilities.ExpressionTrees;
using System.Runtime.CompilerServices;

namespace Signum.Entities
{
    public static class Validator
    {
        static readonly ThreadVariable<bool> inModelBinderVariable = Statics.ThreadVariable<bool>("inModelBinder");
        public static bool InModelBinder
        {
            get { return inModelBinderVariable.Value; }
        }

        public static IDisposable ModelBinderScope()
        {
            var old = inModelBinderVariable.Value;
            inModelBinderVariable.Value = true;
            return new Disposable(() => inModelBinderVariable.Value = old);
        }

        public static Func<ModifiableEntity, PropertyInfo, string?>? GlobalValidation { get; set; }

        static readonly Polymorphic<Dictionary<string, IPropertyValidator>> validators =
            new Polymorphic<Dictionary<string, IPropertyValidator>>(PolymorphicMerger.InheritDictionary, typeof(ModifiableEntity));

        static void GenerateType(Type type)
        {
            giGenerateType.GetInvoker(type)();
        }

        static readonly GenericInvoker<Action> giGenerateType =
            new GenericInvoker<Action>(() => GenerateType<ModifiableEntity>());

        static void GenerateType<T>() where T : ModifiableEntity
        {
            if (validators.GetDefinition(typeof(T)) != null)
                return;

            if(typeof(T) != typeof(ModifiableEntity))
                GenerateType(typeof(T).BaseType!);

            var dic = (from pi in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                       where !pi.HasAttribute<HiddenPropertyAttribute>() && !pi.HasAttribute<ExpressionFieldAttribute>() 
                       select KeyValuePair.Create(pi.Name, (IPropertyValidator)new PropertyValidator<T>(pi))).ToDictionary();

            validators.SetDefinition(typeof(T), dic);
        }

        public static PropertyValidator<T> OverridePropertyValidator<T>(Expression<Func<T, object?>> property) where T : ModifiableEntity
        {
            GenerateType<T>();

            var pi = ReflectionTools.GetPropertyInfo(property);

            var dic = validators.GetDefinition(typeof(T))!;

            PropertyValidator<T>? result = (PropertyValidator<T>?)dic.TryGetC(pi.Name);

            if (result == null)
            {
                result = new PropertyValidator<T>(pi);
                dic.Add(pi.Name, result);
                validators.ClearCache();
            }

            return result;<commit_msg>fix for ExpressionField has setter like TreeEntity.Level<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using Signum.Utilities;
using Signum.Utilities.Reflection;
using System.Reflection;
using System.Linq.Expressions;
using Signum.Utilities.ExpressionTrees;
using System.Runtime.CompilerServices;

namespace Signum.Entities
{
    public static class Validator
    {
        static readonly ThreadVariable<bool> inModelBinderVariable = Statics.ThreadVariable<bool>("inModelBinder");
        public static bool InModelBinder
        {
            get { return inModelBinderVariable.Value; }
        }

        public static IDisposable ModelBinderScope()
        {
            var old = inModelBinderVariable.Value;
            inModelBinderVariable.Value = true;
            return new Disposable(() => inModelBinderVariable.Value = old);
        }

        public static Func<ModifiableEntity, PropertyInfo, string?>? GlobalValidation { get; set; }

        static readonly Polymorphic<Dictionary<string, IPropertyValidator>> validators =
            new Polymorphic<Dictionary<string, IPropertyValidator>>(PolymorphicMerger.InheritDictionary, typeof(ModifiableEntity));

        static void GenerateType(Type type)
        {
            giGenerateType.GetInvoker(type)();
        }

        static readonly GenericInvoker<Action> giGenerateType =
            new GenericInvoker<Action>(() => GenerateType<ModifiableEntity>());

        static void GenerateType<T>() where T : ModifiableEntity
        {
            if (validators.GetDefinition(typeof(T)) != null)
                return;

            if (typeof(T) != typeof(ModifiableEntity))
                GenerateType(typeof(T).BaseType!);

            var dic = (from pi in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                       where !(pi.HasAttribute<HiddenPropertyAttribute>() || (pi.CanWrite == false && pi.HasAttribute<ExpressionFieldAttribute>()))
                       select KeyValuePair.Create(pi.Name, (IPropertyValidator)new PropertyValidator<T>(pi))).ToDictionary();

            validators.SetDefinition(typeof(T), dic);
        }

        public static PropertyValidator<T> OverridePropertyValidator<T>(Expression<Func<T, object?>> property) where T : ModifiableEntity
        {
            GenerateType<T>();

            var pi = ReflectionTools.GetPropertyInfo(property);

            var dic = validators.GetDefinition(typeof(T))!;

            PropertyValidator<T>? result = (PropertyValidator<T>?)dic.TryGetC(pi.Name);

            if (result == null)
            {
                result = new PropertyValidator<T>(pi);
                dic.Add(pi.Name, result);
                validators.ClearCache();
            }

            return result;
{'fraction_non_alphanumeric': 0.09777538571941155, 'fraction_numerical': 0.0, 'mean_word_length': 2.739101274312542, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6316320', 'n_tokens_mistral': 1431, 'n_tokens_neox': 1387, 'n_words': 286}