<commit_before>﻿using DotvvmAcademy.Validation.Dothtml.ValidationTree;
using System.Collections.Generic;
using System.Linq;
using System.Xml.XPath;

namespace DotvvmAcademy.Validation.Dothtml.Constraints
{
    internal class CountConstraint<TNode>
        where TNode : ValidationTreeNode
    {
        public CountConstraint(XPathExpression expression, int count)
        {
            Expression = expression;
            Count = count;
        }

        public int Count { get; }

        public XPathExpression Expression { get; }

        public void Validate(IValidationReporter reporter, NodeLocator locator)
        {
            var nodes = locator.Locate<TNode>(Expression)
                .ToArray();

            // Correct count
            if (nodes.Length == Count)
            {
                return;
            }

            // Incorrect positive count
            if (nodes.Length > 0)
            {
                foreach (var node in nodes)
                {
                    reporter.Report(
                        message: Resources.ERR_WrongCount,
                        arguments: new object[] { Count, Expression.GetControlName() },
                        node: node);
                }
                return;
            }

            // Incorrect zero count with logical parent
            var parentExpression = Expression.GetLogicalParent();
            if (parentExpression != null)
            {
                var parents = locator.Locate(parentExpression);
                ReportParentedMissing(reporter, parents);
            }
            else
            {
                // Incorrect zero count without parent
                ReportMissing(reporter);
            }
        }

        private void ReportMissing(IValidationReporter reporter)
        {
            if (typeof(ValidationDirective).IsAssignableFrom(typeof(TNode)))
            {
                reporter.Report(
                    message: Resources.ERR_MissingDirective,
                    arguments: new object[] { Expression.GetDirectiveName() });
            }
            else if (typeof(ValidationControl).IsAssignableFrom(typeof(TNode)))
            {
                reporter.Report(
                    message: Resources.ERR_MissingControl,
                    arguments: new object[] { Expression.GetControlName(), Expression.Expression });
            }
            else if (typeof(ValidationPropertySetter).IsAssignableFrom(typeof(TNode)))
            {
                reporter.Report(
                    message: Resources.ERR_MissingProperty,
                    arguments: new object[] { Expression.GetPropertyName(), Expression.Expression });
            }
            else
            {
                reporter.Report(
                    message: Resources.ERR_MissingNode,
                    arguments: new object[] { Expression.GetLastSegment(), Expression.Expression });
            }
        }

        private void ReportParentedMissing(IValidationReporter reporter, IEnumerable<ValidationTreeNode> parents)
        {
            if (typeof(ValidationControl).IsAssignableFrom(typeof(TNode)))
            {
                foreach (var parent in parents)
                {
                    reporter.Report(
                        message: Resources.ERR_MissingControlLocal,
                        arguments: new object[] { Expression.GetControlName() },
                        node: parent);
                }
            }
            else if (typeof(ValidationPropertySetter).IsAssignableFrom(typeof(TNode)))
            {
                foreach (var parent in parents)
                {
                    reporter.Report(
                        message: Resources.ERR_MissingPropertyLocal,
                        arguments: new object[] { Expression.GetPropertyName() },
                        node: parent);
                }
            }
            else
            {
                foreach (var parent in parents)
                {
                    reporter.Report(
                        message: Resources.ERR_MissingNodeLocal,
                        arguments: new object[] { Expression.GetLastSegment() },
                        node: parent);
                }
            }
        }
    }
}<commit_msg>Fix missing error about missing elements<commit_after>﻿using DotvvmAcademy.Validation.Dothtml.ValidationTree;
using System.Collections.Generic;
using System.Linq;
using System.Xml.XPath;

namespace DotvvmAcademy.Validation.Dothtml.Constraints
{
    internal class CountConstraint<TNode>
        where TNode : ValidationTreeNode
    {
        public CountConstraint(XPathExpression expression, int count)
        {
            Expression = expression;
            Count = count;
        }

        public int Count { get; }

        public XPathExpression Expression { get; }

        public void Validate(IValidationReporter reporter, NodeLocator locator)
        {
            var nodes = locator.Locate<TNode>(Expression)
                .ToArray();

            // Correct count
            if (nodes.Length == Count)
            {
                return;
            }

            // Incorrect positive count
            if (nodes.Length > 0)
            {
                foreach (var node in nodes)
                {
                    reporter.Report(
                        message: Resources.ERR_WrongCount,
                        arguments: new object[] { Count, Expression.GetControlName() },
                        node: node);
                }
                return;
            }

            // Incorrect zero count with logical parent
            var parentExpression = Expression.GetLogicalParent();
            if (parentExpression != null)
            {
                var parents = locator.Locate(parentExpression)
                    .ToArray();
                if (parents.Length == 0)
                {
                    ReportMissing(reporter);
                }
                else
                {
                    ReportParentedMissing(reporter, parents);
                }
            }
            else
            {
                // Incorrect zero count without parent
                ReportMissing(reporter);
            }
        }

        private void ReportMissing(IValidationReporter reporter)
        {
            if (typeof(ValidationDirective).IsAssignableFrom(typeof(TNode)))
            {
                reporter.Report(
                    message: Resources.ERR_MissingDirective,
                    arguments: new object[] { Expression.GetDirectiveName() });
            }
            else if (typeof(ValidationControl).IsAssignableFrom(typeof(TNode)))
            {
                reporter.Report(
                    message: Resources.ERR_MissingControl,
                    arguments: new object[] { Expression.GetControlName(), Expression.Expression });
            }
            else if (typeof(ValidationPropertySetter).IsAssignableFrom(typeof(TNode)))
            {
                reporter.Report(
                    message: Resources.ERR_MissingProperty,
                    arguments: new object[] { Expression.GetPropertyName(), Expression.Expression });
            }
            else
            {
                reporter.Report(
                    message: Resources.ERR_MissingNode,
                    arguments: new object[] { Expression.GetLastSegment(), Expression.Expression });
            }
        }

        private void ReportParentedMissing(IValidationReporter reporter, IEnumerable<ValidationTreeNode> parents)
        {
            if (typeof(ValidationControl).IsAssignableFrom(typeof(TNode)))
            {
                foreach (var parent in parents)
                {
                    reporter.Report(
                        message: Resources.ERR_MissingControlLocal,
                        arguments: new object[] { Expression.GetControlName() },
                        node: parent);
                }
            }
            else if (typeof(ValidationPropertySetter).IsAssignableFrom(typeof(TNode)))
            {
                foreach (var parent in parents)
                {
                    reporter.Report(
                        message: Resources.ERR_MissingPropertyLocal,
                        arguments: new object[] { Expression.GetPropertyName() },
                        node: parent);
                }
            }
            else
            {
                foreach (var parent in parents)
                {
                    reporter.Report(
                        message: Resources.ERR_MissingNodeLocal,
                        arguments: new object[] { Expression.GetLastSegment() },
                        node: parent);
                }
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.07552526973310619, 'fraction_numerical': 0.00034071550255536625, 'mean_word_length': 1.2926321270502474, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, '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': '829477', 'n_tokens_mistral': 1954, 'n_tokens_neox': 1841, 'n_words': 397}