<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using global::Umbraco.Core;

namespace Our.Umbraco.Ditto
{
    /// <summary>
    /// Extensions methods for <see cref="T:System.Type"/> for inferring type properties.
    /// Most of this code was adapted from the Entity Framework
    /// </summary>
    internal static class TypeInferenceExtensions
    {
        /// <summary>
        /// Determines whether the specified type is an enumerable of the given argument type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="typeArgument">The generic type argument.</param>
        /// <returns>
        /// True if the type is an enumerable of the given argument type otherwise; false.
        /// </returns>
        public static bool IsEnumerableOfType(this Type type, Type typeArgument)
        {
            Type t = type.TryGetElementType(typeof(IEnumerable<>));
            return t != null && typeArgument.IsAssignableFrom(t);
        }

        /// <summary>
        /// Determines whether the specified type is a collection type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>True if the type is a collection type otherwise; false.</returns>
        public static bool IsCollectionType(this Type type)
        {
            return type.TryGetElementType(typeof(ICollection<>)) != null;
        }

        /// <summary>
        /// Determines whether the specified type is an enumerable type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>True if the type is an enumerable type otherwise; false.</returns>
        public static bool IsEnumerableType(this Type type)
        {
            return type.TryGetElementType(typeof(IEnumerable<>)) != null;
        }

        /// <summary>
        /// Determines whether the specified type is an enumerable type containing a 
        /// key value pair as the generic type parameter.
        /// <remarks>
        /// <see cref="M:Enumerable.FirstOrDefault"/> will throw an error when passed an
        /// <see cref="T:IEnumerable{KeyValuePair{,}}"/> this includes <see cref="T:Dictionary{,}"/>.
        /// </remarks>
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>
        /// True if the type is an enumerable type with the generic parameter of a key/value 
        /// pair otherwise; false.</returns>
        public static bool IsEnumerableOfKeyValueType(this Type type)
        {
            return type.TryGetElementType(typeof(IDictionary<,>)) != null ||
                (type.IsEnumerableType() && type.IsGenericType && type.GenericTypeArguments.Any()
                 && type.GenericTypeArguments[0].IsGenericType
                 && type.GenericTypeArguments[0].GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
        }

        /// <summary>
        /// Determines whether the specified type is an enumerable type that is safe to cast
        /// following processing via a type converter.
        /// <remarks>
        /// This should exclude <see cref="T:string"/>, <see cref="T:Dictionary{,}"/>
        /// </remarks>
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>True if the type is a cast-safe, enumerable type otherwise; false.</returns>
        public static bool IsCastableEnumerableType(this Type type)
        {
            // String, though enumerable have no generic arguments.
            // Types with more than one generic argument cnnot be cast. 
            // Dictionary, though enumerable, requires linq to convert and shouldn't be attempted anyway.
            return type.IsEnumerableType() && type.GenericTypeArguments.Any()<commit_msg>Fix typo/grammar.<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using global::Umbraco.Core;

namespace Our.Umbraco.Ditto
{
    /// <summary>
    /// Extensions methods for <see cref="T:System.Type"/> for inferring type properties.
    /// Most of this code was adapted from the Entity Framework
    /// </summary>
    internal static class TypeInferenceExtensions
    {
        /// <summary>
        /// Determines whether the specified type is an enumerable of the given argument type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="typeArgument">The generic type argument.</param>
        /// <returns>
        /// True if the type is an enumerable of the given argument type; otherwise, false.
        /// </returns>
        public static bool IsEnumerableOfType(this Type type, Type typeArgument)
        {
            Type t = type.TryGetElementType(typeof(IEnumerable<>));
            return t != null && typeArgument.IsAssignableFrom(t);
        }

        /// <summary>
        /// Determines whether the specified type is a collection type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>True if the type is a collection type; otherwise, false.</returns>
        public static bool IsCollectionType(this Type type)
        {
            return type.TryGetElementType(typeof(ICollection<>)) != null;
        }

        /// <summary>
        /// Determines whether the specified type is an enumerable type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>True if the type is an enumerable type; otherwise, false.</returns>
        public static bool IsEnumerableType(this Type type)
        {
            return type.TryGetElementType(typeof(IEnumerable<>)) != null;
        }

        /// <summary>
        /// Determines whether the specified type is an enumerable type containing a 
        /// key value pair as the generic type parameter.
        /// <remarks>
        /// <see cref="M:Enumerable.FirstOrDefault"/> will throw an error when passed an
        /// <see cref="T:IEnumerable{KeyValuePair{,}}"/> this includes <see cref="T:Dictionary{,}"/>.
        /// </remarks>
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>
        /// True if the type is an enumerable type with the generic parameter of a key/value 
        /// pair; otherwise, false.</returns>
        public static bool IsEnumerableOfKeyValueType(this Type type)
        {
            return type.TryGetElementType(typeof(IDictionary<,>)) != null ||
                (type.IsEnumerableType() && type.IsGenericType && type.GenericTypeArguments.Any()
                 && type.GenericTypeArguments[0].IsGenericType
                 && type.GenericTypeArguments[0].GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
        }

        /// <summary>
        /// Determines whether the specified type is an enumerable type that is safe to cast
        /// following processing via a type converter.
        /// <remarks>
        /// This should exclude <see cref="T:string"/>, <see cref="T:Dictionary{,}"/>
        /// </remarks>
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>True if the type is a cast-safe, enumerable type; otherwise, false.</returns>
        public static bool IsCastableEnumerableType(this Type type)
        {
            // String, though enumerable have no generic arguments.
            // Types with more than one generic argument cannot be cast. 
            // Dictionary, though enumerable, requires linq to convert and shouldn't be attempted anyway.
            return type.IsEnumerableType() && type.GenericTypeArguments.Any()
{'fraction_non_alphanumeric': 0.12430939226519337, 'fraction_numerical': 0.0005261773217574323, 'mean_word_length': 2.154771784232365, 'pattern_counts': {'":': 0, '<': 101, '<?xml version=': 0, '>': 101, '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': '533684', 'n_tokens_mistral': 1903, 'n_tokens_neox': 1874, 'n_words': 627}