<commit_before>﻿// Copyright (c) <NAME>. All rights reserved. See license.txt in the project root for license information.

namespace Aqua.TypeSystem
{
    using Aqua.Extensions;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;

    public partial class TypeResolver : ITypeResolver
    {
        private sealed class EqualityComparer : IEqualityComparer<TypeInfo>, IEqualityComparer<PropertyInfo>
        {
            public static readonly EqualityComparer Instance = new EqualityComparer();

            private EqualityComparer()
            {
            }

            public bool Equals(TypeInfo x, TypeInfo y)
            {
                if (ReferenceEquals(x, y))
                {
                    return true;
                }

                if (ReferenceEquals(null, x))
                {
                    return false;
                }

                if (ReferenceEquals(null, y))
                {
                    return false;
                }

                return string.Equals(x.ToString(), y.ToString())
                    && x.Properties.CollectionEquals(y.Properties, this);
            }

            public int GetHashCode(TypeInfo obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return 0;
                }

                return (obj.ToString().GetHashCode() * 397) ^ obj.Properties?.Select(x => x.Name).GetCollectionHashCode() ?? 0;
            }

            public bool Equals(PropertyInfo x, PropertyInfo y)
            {
                if (ReferenceEquals(x, y))
                {
                    return true;
                }

                if (ReferenceEquals(null, x))
                {
                    return false;
                }

                if (ReferenceEquals(null, y))
                {
                    return false;
                }

                return string.Equals(x.Name, y.Name)
                    && string.Equals(x.PropertyType?.ToString(), y.PropertyType?.ToString()); // break potential cyclic loop by comparing type name only
            }

            public int GetHashCode(PropertyInfo obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return 0;
                }
                
                return (obj.Name.GetHashCode() * 397) ^ obj.PropertyType?.ToString().GetHashCode() ?? 0;
            }
        }

        private static readonly ITypeResolver _defaultTypeResolver = new TypeResolver();

        private static ITypeResolver _instance;

        private readonly TransparentCache<TypeInfo, Type> _typeCache = new TransparentCache<TypeInfo, Type>(comparer: EqualityComparer.Instance);

        /// <summary>
        /// Sets or gets an instance of ITypeResolver.
        /// </summary>
        /// <remarks>
        /// Setting this property allows for registring a custom type resolver statically. 
        /// Setting this property to null makes it fall-back to the default resolver.<commit_msg>set bracket for proper scoping of ?? (null-coalescing) operator.<commit_after>﻿// Copyright (c) <NAME>. All rights reserved. See license.txt in the project root for license information.

namespace Aqua.TypeSystem
{
    using Aqua.Extensions;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;

    public partial class TypeResolver : ITypeResolver
    {
        private sealed class EqualityComparer : IEqualityComparer<TypeInfo>, IEqualityComparer<PropertyInfo>
        {
            public static readonly EqualityComparer Instance = new EqualityComparer();

            private EqualityComparer()
            {
            }

            public bool Equals(TypeInfo x, TypeInfo y)
            {
                if (ReferenceEquals(x, y))
                {
                    return true;
                }

                if (ReferenceEquals(null, x))
                {
                    return false;
                }

                if (ReferenceEquals(null, y))
                {
                    return false;
                }

                return string.Equals(x.ToString(), y.ToString())
                    && x.Properties.CollectionEquals(y.Properties, this);
            }

            public int GetHashCode(TypeInfo obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return 0;
                }

                return (obj.ToString().GetHashCode() * 397) ^ (obj.Properties?.Select(x => x.Name).GetCollectionHashCode() ?? 0);
            }

            public bool Equals(PropertyInfo x, PropertyInfo y)
            {
                if (ReferenceEquals(x, y))
                {
                    return true;
                }

                if (ReferenceEquals(null, x))
                {
                    return false;
                }

                if (ReferenceEquals(null, y))
                {
                    return false;
                }

                return string.Equals(x.Name, y.Name)
                    && string.Equals(x.PropertyType?.ToString(), y.PropertyType?.ToString()); // break potential cyclic loop by comparing type name only
            }

            public int GetHashCode(PropertyInfo obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return 0;
                }
                
                return (obj.Name.GetHashCode() * 397) ^ (obj.PropertyType?.ToString().GetHashCode() ?? 0);
            }
        }

        private static readonly ITypeResolver _defaultTypeResolver = new TypeResolver();

        private static ITypeResolver _instance;

        private readonly TransparentCache<TypeInfo, Type> _typeCache = new TransparentCache<TypeInfo, Type>(comparer: EqualityComparer.Instance);

        /// <summary>
        /// Sets or gets an instance of ITypeResolver.
        /// </summary>
        /// <remarks>
        /// Setting this property allows for registring a custom type resolver statically. 
        /// Setting this property to null makes it fall-back to the default resolver.
{'fraction_non_alphanumeric': 0.08484653704001285, 'fraction_numerical': 0.0032138839787883657, 'mean_word_length': 1.376479572355861, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 21, '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': '1540192', 'n_tokens_mistral': 1522, 'n_tokens_neox': 1400, 'n_words': 388}