<commit_before>using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace AsmResolver.DotNet.Signatures.Types.Parsing
{
    public class TypeNameParser
    {
        private static readonly SignatureComparer Comparer = new SignatureComparer();
        
        // https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/specifying-fully-qualified-type-names

        public static TypeSignature Parse(ModuleDefinition module, string canonicalName)
        {
            var lexer = new TypeNameLexer(new StringReader(canonicalName));
            var parser = new TypeNameParser(module, lexer);
            return parser.ParseTypeSpec();
        }

        private readonly ModuleDefinition _module;
        private readonly TypeNameLexer _lexer;

        private TypeNameParser(ModuleDefinition module, TypeNameLexer lexer)
        {
            _module = module ?? throw new ArgumentNullException(nameof(module));
            _lexer = lexer ?? throw new ArgumentNullException(nameof(lexer));
        }

        private TypeSignature ParseTypeSpec()
        {
            var typeSpec = ParseSimpleTypeSpec();
            
            if (TryExpect(TypeNameTerminal.Ampersand).HasValue)
                typeSpec = new ByReferenceTypeSignature(typeSpec);
            
            // See if the type full name contains an assembly ref.
            var scope = TryExpect(TypeNameTerminal.Comma).HasValue
                ? (IResolutionScope) ParseAssemblyNameSpec()
                : _module;

            // Ensure corlib type sigs are used.
            if (Comparer.Equals(scope, _module.CorLibTypeFactory.CorLibScope))
            {
                var corlibType = _module.CorLibTypeFactory.FromType(typeSpec);
                if (corlibType != null)
                    return corlibType;
            }
            
            // Update scope.
            var reference = (TypeReference) typeSpec.GetUnderlyingTypeDefOrRef();
            while (reference.Scope is TypeReference parent)
                reference = parent;
            reference.Scope = scope;

            return typeSpec;
        }

        private TypeSignature ParseSimpleTypeSpec()
        {
            var typeName = ParseTypeName();
            return _lexer.Peek().Terminal switch
            {
                TypeNameTerminal.Star => ParsePointerTypeSpec(typeName),
                TypeNameTerminal.OpenBracket => ParseArrayOrGenericTypeSpec(typeName),
                _ => typeName
            };
        }

        private TypeSignature ParsePointerTypeSpec(TypeSignature typeName)
        {
            Expect(TypeNameTerminal.Star);
            return new PointerTypeSignature(typeName);
        }

        private TypeSignature ParseArrayOrGenericTypeSpec(TypeSignature typeName)
        {
            Expect(TypeNameTerminal.OpenBracket);

            switch (_lexer.Peek().Terminal)
            {
                case TypeNameTerminal.OpenBracket:
                    return ParseGenericTypeSpec(typeName);
                
                default:
                    return ParseArrayTypeSpec(typeName);
            }
        }

        private TypeSignature ParseArrayTypeSpec(TypeSignature typeName)<commit_msg>Move ByRef parsing to separate method.<commit_after>using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace AsmResolver.DotNet.Signatures.Types.Parsing
{
    public class TypeNameParser
    {
        private static readonly SignatureComparer Comparer = new SignatureComparer();
        
        // https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/specifying-fully-qualified-type-names

        public static TypeSignature Parse(ModuleDefinition module, string canonicalName)
        {
            var lexer = new TypeNameLexer(new StringReader(canonicalName));
            var parser = new TypeNameParser(module, lexer);
            return parser.ParseTypeSpec();
        }

        private readonly ModuleDefinition _module;
        private readonly TypeNameLexer _lexer;

        private TypeNameParser(ModuleDefinition module, TypeNameLexer lexer)
        {
            _module = module ?? throw new ArgumentNullException(nameof(module));
            _lexer = lexer ?? throw new ArgumentNullException(nameof(lexer));
        }

        private TypeSignature ParseTypeSpec()
        {
            // Parse type signature.
            var typeSpec = ParseSimpleTypeSpec();
            
            // See if the type full name contains an assembly ref.
            var scope = TryExpect(TypeNameTerminal.Comma).HasValue
                ? (IResolutionScope) ParseAssemblyNameSpec()
                : _module;

            // Ensure corlib type sigs are used.
            if (Comparer.Equals(scope, _module.CorLibTypeFactory.CorLibScope))
            {
                var corlibType = _module.CorLibTypeFactory.FromType(typeSpec);
                if (corlibType != null)
                    return corlibType;
            }
            
            // Update scope.
            var reference = (TypeReference) typeSpec.GetUnderlyingTypeDefOrRef();
            while (reference.Scope is TypeReference parent)
                reference = parent;
            reference.Scope = scope;

            return typeSpec;
        }

        private TypeSignature ParseSimpleTypeSpec()
        {
            // Parse type name.
            var typeName = ParseTypeName();
            
            // Check for annotations.
            return _lexer.Peek().Terminal switch
            {
                TypeNameTerminal.Ampersand => ParseByReferenceTypeSpec(typeName),
                TypeNameTerminal.Star => ParsePointerTypeSpec(typeName),
                TypeNameTerminal.OpenBracket => ParseArrayOrGenericTypeSpec(typeName),
                _ => typeName
            };
        }

        private TypeSignature ParseByReferenceTypeSpec(TypeSignature typeName)
        {
            Expect(TypeNameTerminal.Ampersand);
            return new ByReferenceTypeSignature(typeName);
        }

        private TypeSignature ParsePointerTypeSpec(TypeSignature typeName)
        {
            Expect(TypeNameTerminal.Star);
            return new PointerTypeSignature(typeName);
        }

        private TypeSignature ParseArrayOrGenericTypeSpec(TypeSignature typeName)
        {
            Expect(TypeNameTerminal.OpenBracket);

            switch (_lexer.Peek().Terminal)
            {
                case TypeNameTerminal.OpenBracket:
                    return ParseGenericTypeSpec(typeName);
                
                default:
                    return ParseArrayTypeSpec(typeName);
            }
        }

        private TypeSignature ParseArrayTypeSpec(TypeSignature typeName)
{'fraction_non_alphanumeric': 0.06923076923076923, 'fraction_numerical': 0.0, 'mean_word_length': 1.9524421593830334, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 10, 'https://': 2, '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': '1088130', 'n_tokens_mistral': 1692, 'n_tokens_neox': 1613, 'n_words': 354}