<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace Dextem
{
    /// <summary>
    /// Controls name processing of method 'M:' and type 'T:' &lt;member&gt; nodes. This class cannot be inherited.
    /// </summary>
    public sealed class MethodTypeProcessor : BaseProcessor
    {
        /// <summary>
        /// Creates a new instance of MethodTypeProcessor using the given ProcessorRegistry.
        /// </summary>
        /// <param name="registry">The ProcessorRegistry instance to use.</param>
        public MethodTypeProcessor(ProcessorRegistry registry) : base(registry) { }

        /// <summary>
        /// Executes name processing of the curernt method 'M:' or type 'T:' &lt;member&gt; element.
        /// </summary>
        /// <param name="writer">The current StringWriter to use.</param>
        /// <param name="root">The current root element to process.</param>
        /// <param name="context">The current processing context.</param>
        /// <returns>The updated processing context.</returns>
        public override Dictionary<XName, string> Process(StringWriter writer, XElement root, Dictionary<XName, string> context)
        {
            var memberName = root.Attribute(XName.Get("name")).Value;
            char memberType = memberName[0];

            if (memberType == 'M')
            {
                memberName = RearrangeTypeParametersInContext(root, memberName, context, false);
                memberName = RearrangeParametersInContext(root, memberName, context);
            }

            context["memberName"] = memberName;

            if (memberType == 'T')
            {
                var typeNameStartIndex = 3 + context["assembly"].Length;
                var scrubbedName = this.ReplaceForTypeParameters(root, memberName, false, context);
                var shortMemberName = scrubbedName.Substring(typeNameStartIndex);
                writer.WriteLine("\n## {0}\n", shortMemberName);
                context["typeName"] = shortMemberName;
            }

            context["memberType"] = memberType.ToString();

            context["lastNode"] = memberName;

            return base.Process(writer, root, context);
        }

        private string RearrangeParametersInContext(XElement methodMember, string memberName, Dictionary<XName, string> context)
        {
            string methodPrototype = memberName;
            Match match = Regex.Match(methodPrototype, "\\((.*)\\)");
            string parameterString = match.Groups[1].Value.Replace(" ", "");
            string[] parameterTypes = parameterString.Split(',');

            if (parameterTypes.Length == 0)
            {
                // nothing to do...
                return methodPrototype;
            }

            List<XElement> paramElems = new List<XElement>(methodMember.Elements("param"));
            if (parameterTypes.Length != paramElems.Count)
            {
                // the parameter count do not match, we can't do the rearrangement.
                return methodPrototype;
            }

            string newParamString = "";
            for (int i = 0; i < paramElems.Count; i++)
            {
                XElement paramElem = paramElems[i];
                string paramName = paramElem.Attribute(XName.Get("name")).Value;
                string paramType = parameterTypes[i];
                if (newParamString != "")
                {
                    newParamString += ", ";
                }
                newParamString += paramName;
                context[paramName] = paramType;
            }

            string newMethodPrototype = Regex.Replace(methodPrototype,
                "\\(.*\\)",
                "(" + newParamString + ")");

            return newMethodPrototype;
        }

        private string RearrangeTypeParametersInContext(XElement member, string memberName, Dictionary<XName, string> context, bool skipReplace)
        {<commit_msg>Enhanced parameter rearranging using more robust parameter type retrieval<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace Dextem
{
    /// <summary>
    /// Controls name processing of method 'M:' and type 'T:' &lt;member&gt; nodes. This class cannot be inherited.
    /// </summary>
    public sealed class MethodTypeProcessor : BaseProcessor
    {
        /// <summary>
        /// Creates a new instance of MethodTypeProcessor using the given ProcessorRegistry.
        /// </summary>
        /// <param name="registry">The ProcessorRegistry instance to use.</param>
        public MethodTypeProcessor(ProcessorRegistry registry) : base(registry) { }

        /// <summary>
        /// Executes name processing of the curernt method 'M:' or type 'T:' &lt;member&gt; element.
        /// </summary>
        /// <param name="writer">The current StringWriter to use.</param>
        /// <param name="root">The current root element to process.</param>
        /// <param name="context">The current processing context.</param>
        /// <returns>The updated processing context.</returns>
        public override Dictionary<XName, string> Process(StringWriter writer, XElement root, Dictionary<XName, string> context)
        {
            var memberName = root.Attribute(XName.Get("name")).Value;
            char memberType = memberName[0];

            if (memberType == 'M')
            {
                memberName = RearrangeTypeParametersInContext(root, memberName, context, false);
                memberName = RearrangeParametersInContext(root, memberName, context);
            }

            context["memberName"] = memberName;

            if (memberType == 'T')
            {
                var typeNameStartIndex = 3 + context["assembly"].Length;
                var scrubbedName = this.ReplaceForTypeParameters(root, memberName, false, context);
                var shortMemberName = scrubbedName.Substring(typeNameStartIndex);
                writer.WriteLine("\n## {0}\n", shortMemberName);
                context["typeName"] = shortMemberName;
            }

            context["memberType"] = memberType.ToString();

            context["lastNode"] = memberName;

            return base.Process(writer, root, context);
        }

        private List<string> GetParameterTypes(string memberName)
        {
            var parameterTypes = new List<string>();

            Match match = Regex.Match(memberName, "\\((.*)\\)");

            // Groups[0] = (Type, Type, Type)
            // Groups[1] = Type, Type, Type

            if (match.Groups.Count < 1)
            {
                return parameterTypes;
            }

            string rawParameterString = string.Empty;

            if (match.Groups.Count == 1)
            {
                rawParameterString = match.Groups[0].Value.Replace("(", "").Replace(")", "").Replace(" ", "");
            }

            if (match.Groups.Count == 2)
            {
                rawParameterString = match.Groups[1].Value.Replace(" ", "");
            }

            var rawParameterArray = rawParameterString.Split(',');

            for (var i = 0; i < rawParameterArray.Length; i++)
            {
                var raw = rawParameterArray[i];

                var isGeneric = (raw.Contains("{") || raw.Contains("<") || raw.Contains("}") || raw.Contains(">"));
                var isOpenOnly = (isGeneric && !(raw.Contains("}") || raw.Contains(">")));

                if (!isGeneric || isOpenOnly)
                {
                    parameterTypes.Add(raw);
                    continue;
                }

                var isCloseOnly = (isGeneric && !(raw.Contains("{") || raw.Contains("<")));

                if (isCloseOnly)
                {
                    parameterTypes[parameterTypes.Count - 1] += raw;
                    continue;
                }
            }

            return parameterTypes;
        }

        private string RearrangeParametersInContext(XElement methodMember, string memberName, Dictionary<XName, string> context)
        {
            var parameterTypes = this.GetParameterTypes(memberName);

            List<XElement> paramElems = new List<XElement>(methodMember.Elements("param"));
            if (parameterTypes.Count != paramElems.Count)
            {
                // the parameter count do not match, we can't do the rearrangement.
                return memberName;
            }

            string newParamString = "";
            for (int i = 0; i < paramElems.Count; i++)
            {
                XElement paramElem = paramElems[i];
                string paramName = paramElem.Attribute(XName.Get("name")).Value;
                string paramType = parameterTypes[i];
                if (newParamString != "")
                {
                    newParamString += ", ";
                }
                newParamString += paramName;
                context[paramName] = paramType;
            }

            string newMethodPrototype = Regex.Replace(memberName,
                "\\(.*\\)",
                "(" + newParamString + ")");

            return newMethodPrototype;
        }

        private string RearrangeTypeParametersInContext(XElement member, string memberName, Dictionary<XName, string> context, bool skipReplace)
        {
{'fraction_non_alphanumeric': 0.11729243786356425, 'fraction_numerical': 0.002009518773135907, 'mean_word_length': 1.9015035286897821, 'pattern_counts': {'":': 0, '<': 55, '<?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': '7122996', 'n_tokens_mistral': 2379, 'n_tokens_neox': 2265, 'n_words': 568}