<commit_before>﻿namespace Gu.Wpf.ValidationScope
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Media;

    /// <summary>Implementation.</summary>
    public static partial class Scope
    {
        private static void UpdateParent(this DependencyObject source, IEnumerable<ValidationError> removed, IEnumerable<ValidationError> added)
        {
            if (source is null)
            {
                return;
            }

            var parent = VisualTreeHelper.GetParent(source) as FrameworkElement;
            if (parent is null || GetForInputTypes(parent) is null)
            {
                return;
            }

            var childNode = GetNode(source) as ErrorNode;
            if (childNode is null)
            {
                return;
            }

            var parentNode = GetNode(parent) as ErrorNode;

            if (IsScopeFor(parent, source))
            {
                if (parentNode is null)
                {
#pragma warning disable IDISP001, CA2000 // Dispose created. Disposed in SetNode.
                    parentNode = new ScopeNode(parent);
#pragma warning restore IDISP001, CA2000 // Dispose created.
                }

                parentNode.ChildCollection.TryAdd(childNode);
                parentNode.ErrorCollection.Remove(removed);
                parentNode.ErrorCollection.Add(added.Where(e => parent.IsScopeFor(e)).AsReadOnly());
                SetNode(parent, parentNode);
            }
            else
            {
                if (parentNode is null)
                {
                    return;
                }

                parentNode.ChildCollection.Remove(childNode);
                parentNode.ErrorCollection.Remove(removed);
                parentNode.ErrorCollection.Remove(childNode.Errors);
                if (parentNode is ScopeNode { Errors: { Count: 0 } })
                {
                    SetNode(parent, ValidNode.Default);
                }
            }
        }

        private static bool IsScopeFor(this DependencyObject parent, ValidationError error)
        {
            if (parent is FrameworkElement fe &&
                GetForInputTypes(fe) is { } inputTypes)
            {
                if (inputTypes.Contains(typeof(Scope)))
                {
                    return true;
                }

                return inputTypes.Contains(error.Target());
            }

            return false;
        }

        private static bool IsScopeFor(this DependencyObject parent, DependencyObject source)
        {
            if (parent is null || source is null)
            {
                return false;
            }

            if (parent is FrameworkElement fe &&
                GetForInputTypes(fe) is { } inputTypes &&
                GetNode(source) is { } node)
            {
                if (node is ValidNode || node.Errors.Count == 0)
                {
                    return false;
                }

                if (inputTypes.Contains(typeof(Scope)) && node is ScopeNode)
                {
                    return true;
                }

                foreach (var error in GetErrors(source))
                {
                    if (inputTypes.Contains(error.Target()))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        private static DependencyObject Target(this ValidationError error)
        {
            var binding = error?.BindingInError;
            if (binding is null)
            {
                throw new ArgumentNullException(nameof(error), "error.BindingInError == null");
            }

            if (binding is BindingExpressionBase bindingExpression)
            {
                return bindingExpression.Target;
            }

            throw new ArgumentOutOfRangeException(nameof(error), error, $"ValidationError.BindingInError == {binding}");
        }
    }
}
<commit_msg>Minor optimization.<commit_after>﻿namespace Gu.Wpf.ValidationScope
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Media;

    /// <summary>Implementation.</summary>
    public static partial class Scope
    {
        private static void UpdateParent(this DependencyObject source, IEnumerable<ValidationError> removed, IEnumerable<ValidationError> added)
        {
            if (source is null)
            {
                return;
            }

            var parent = VisualTreeHelper.GetParent(source) as FrameworkElement;
            if (parent is null || GetForInputTypes(parent) is null)
            {
                return;
            }

            var childNode = GetNode(source) as ErrorNode;
            if (childNode is null)
            {
                return;
            }

            var parentNode = GetNode(parent) as ErrorNode;

            if (IsScopeFor(parent, source))
            {
                if (parentNode is null)
                {
#pragma warning disable IDISP001, CA2000 // Dispose created. Disposed in SetNode.
                    parentNode = new ScopeNode(parent);
#pragma warning restore IDISP001, CA2000 // Dispose created.
                }

                parentNode.ChildCollection.TryAdd(childNode);
                parentNode.ErrorCollection.Remove(removed);
                parentNode.ErrorCollection.Add(added.Where(e => parent.IsScopeFor(e)).AsReadOnly());
                SetNode(parent, parentNode);
            }
            else
            {
                if (parentNode is null)
                {
                    return;
                }

                parentNode.ChildCollection.Remove(childNode);
                parentNode.ErrorCollection.Remove(removed);
                parentNode.ErrorCollection.Remove(childNode.Errors);
                if (parentNode is ScopeNode { Errors: { Count: 0 } })
                {
                    SetNode(parent, ValidNode.Default);
                }
            }
        }

        private static bool IsScopeFor(this DependencyObject parent, ValidationError error)
        {
            if (parent is FrameworkElement fe &&
                GetForInputTypes(fe) is { } inputTypes)
            {
                foreach (var inputType in inputTypes)
                {
                    if (inputType == typeof(Scope))
                    {
                        return true;
                    }

                    if (inputType.IsInstanceOfType(error.Target()))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        private static bool IsScopeFor(this DependencyObject parent, DependencyObject source)
        {
            if (parent is null || source is null)
            {
                return false;
            }

            if (parent is FrameworkElement fe &&
                GetForInputTypes(fe) is { } inputTypes &&
                GetNode(source) is { } node)
            {
                if (node is ValidNode || node.Errors.Count == 0)
                {
                    return false;
                }

                if (inputTypes.Contains(typeof(Scope)) && node is ScopeNode)
                {
                    return true;
                }

                foreach (var error in GetErrors(source))
                {
                    if (inputTypes.Contains(error.Target()))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        private static DependencyObject Target(this ValidationError error)
        {
            var binding = error?.BindingInError;
            if (binding is null)
            {
                throw new ArgumentNullException(nameof(error), "error.BindingInError == null");
            }

            if (binding is BindingExpressionBase bindingExpression)
            {
                return bindingExpression.Target;
            }

            throw new ArgumentOutOfRangeException(nameof(error), error, $"ValidationError.BindingInError == {binding}");
        }
    }
}

{'fraction_non_alphanumeric': 0.07642102764922273, 'fraction_numerical': 0.0037973181440607573, 'mean_word_length': 1.2858692704095471, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, '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': '1549915', 'n_tokens_mistral': 2057, 'n_tokens_neox': 1882, 'n_words': 459}