<commit_before>﻿/*
	Copyright (c) 2016 <NAME>
	
	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

	License: https://opensource.org/licenses/MIT
*/

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

// ReSharper disable once CheckNamespace
namespace System
{
	public static class TypeActivator
	{
		private struct ConstructorSignature : IEquatable<ConstructorSignature>
		{
			private readonly Type type;
			private readonly Type arg1Type;
			private readonly Type arg2Type;
			private readonly Type arg3Type;
			private readonly Type arg4Type;

			public ConstructorSignature(Type type, Type arg1Type, Type arg2Type = null, Type arg3Type = null, Type arg4Type = null)
			{
				if (type == null) throw new ArgumentNullException("type");
				if (arg1Type == null) throw new ArgumentNullException("arg1Type");

				this.type = type;
				this.arg1Type = arg1Type;
				this.arg2Type = arg2Type ?? typeof(void);
				this.arg3Type = arg3Type ?? typeof(void);
				this.arg4Type = arg4Type ?? typeof(void);
			}

			public override int GetHashCode()
			{
				return unchecked(this.type.GetHashCode() + this.arg1Type.GetHashCode() + this.arg2Type.GetHashCode() + this.arg3Type.GetHashCode() + this.arg4Type.GetHashCode());
			}
			public override bool Equals(object obj)
			{
				if (obj == null || !(obj is ConstructorSignature))
					return false;
				return this.Equals((ConstructorSignature)obj);
			}
			public bool Equals(ConstructorSignature other)
			{
				return this.type == other.type && this.arg1Type == other.arg1Type && this.arg2Type == other.arg2Type && this.arg3Type == other.arg3Type && this.arg4Type == other.arg4Type;
			}

			public override string ToString() { return string.Format("{0}({1}, {2}, {3}, {4})", this.type.Name, this.arg1Type.Name, this.arg2Type.Name, this.arg3Type.Name, this.arg4Type.Name); }
		}

		private static readonly Dictionary<Type, Func<object>> DefaultConstructorCache = new Dictionary<Type, Func<object>>();
		private static readonly Dictionary<ConstructorSignature, Delegate> CustomConstructorCache = new Dictionary<ConstructorSignature, Delegate>();
		private static readonly HashSet<string> ConstructorSubstitutionMembers = new HashSet<string>(new[] { "Empty", "Default", "Instance" }, StringComparer.OrdinalIgnoreCase);

#if !NETSTANDARD
		public static object CreateInstance(Type type)
		{
			return CreateInstance(type, forceCreate: false);
		}
		public static object CreateInstance(Type type, bool forceCreate)
#else
		public static object CreateInstance(Type type)
#endif
		{
			if (type == null) throw new ArgumentNullException("type");

			var constructorFn = default(Func<object>);
			lock (DefaultConstructorCache)
			{
				if (DefaultConstructorCache.TryGetValue(type, out constructorFn) == false)
				{
#if !NETSTANDARD
					var typeInfo = type;
					var constructors = typeInfo.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
					var publicEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && c.IsPublic && c.IsStatic == false);
					var privateEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && !c.IsPublic && c.IsStatic == false);
					var instanceField = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).FirstOrDefault(f =>
						ConstructorSubstitutionMembers.Contains(f.Name) &&
						type.IsAssignableFrom(f.FieldType)
					);
					var instanceProperty = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).FirstOrDefault(p =>
						ConstructorSubstitutionMembers.Contains(p.Name) &&
						type.IsAssignableFrom(p.PropertyType) &&
						p.CanRead && p.GetIndexParameters().Length == 0
					);
#else
					var typeInfo = type.GetTypeInfo();
					var constructors = typeInfo.DeclaredConstructors.ToList();
					var publicEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && c.IsPublic && c.IsStatic == false);
					var privateEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && c.IsPublic == false && c.IsStatic == false);
					var instanceField = type.GetRuntimeFields().FirstOrDefault(f =>
						f.IsStatic &&
						ConstructorSubstitutionMembers.Contains(f.Name) &&
						IsAssignableFrom(type, f.FieldType)
					);
					var instanceProperty = type.GetRuntimeProperties().FirstOrDefault(p =>
						p.GetMethod != null &&
						p.GetMethod.IsStatic &&
						ConstructorSubstitutionMembers.Contains(p.Name) &&
						IsAssignableFrom(type, p.PropertyType) &&
						p.GetIndexParameters().Length == 0
					);
#endif

					if (publicEmptyConstructor != null)
					{
						var createNewObjectExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.New(publicEmptyConstructor),
								typeof(object)
							)
						);

						constructorFn = createNewObjectExpr.Compile();
					}
					else if (instanceField != null)
					{
						var getInstanceFieldExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.Field(null, instanceField),
								typeof(object)
							)
						);
						constructorFn = getInstanceFieldExpr.Compile();
					}
					else if (instanceProperty != null)
					{
						var getInstancePropertyExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.Property(null, instanceProperty),
								typeof(object)
							)
						);
						constructorFn = getInstancePropertyExpr.Compile();
					}
					else if (privateEmptyConstructor != null)
					{
						var createNewObjectExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.New(privateEmptyConstructor),
								typeof(object)
							)
						);

						constructorFn = createNewObjectExpr.Compile();
					}
					else if (type.IsArray && type.GetArrayRank() == 1)
					{
						var elementType = type.GetElementType();
						Debug.Assert(elementType != null, "elementType != null");
						var createNewArrayExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.Constant(Array.CreateInstance(elementType, 0)),
								typeof(object)
							)
						);

						constructorFn = createNewArrayExpr.Compile();
					}
					else if (typeInfo.IsValueType)
					{
						var createNewValueTypeExpr = Expression.Lambda<Func<object>>
						(
							Expression.Constant
							(
								Activator.CreateInstance(type),
								typeof(object)
							)
						);

						constructorFn = createNewValueTypeExpr.Compile();
					}

					DefaultConstructorCache[type] = constructorFn;
				}
			}

#if !NETSTANDARD
			if (constructorFn == null && forceCreate)
				return Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(type);
#endif
			if (constructorFn == null)
				throw new ArgumentException(string.Format("Type '{0}' does not contains default empty constructor.", type), "type");
			else
				return constructorFn();
		}
		public static object CreateInstance<Arg1T>(Type type, Arg1T arg1)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance<Arg1T, object, object, object>(type, arg1, null, null, null, 1);
		}
		public static object CreateInstance<Arg1T, Arg2T>(Type type, Arg1T arg1, Arg2T arg2)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance<Arg1T, Arg2T, object, object>(type, arg1, arg2, null, null, 2);
		}
		public static object CreateInstance<Arg1T, Arg2T, Arg3T>(Type type, Arg1T arg1, Arg2T arg2, Arg3T arg3)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance<Arg1T, Arg2T, Arg3T, object>(type, arg1, arg2, arg3, null, 3);
		}
		public static object CreateInstance<Arg1T, Arg2T, Arg3T, Arg4T>(Type type, Arg1T arg1, Arg2T arg2, Arg3T arg3, Arg4T arg4)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance(type, arg1, arg2, arg3, arg4, 4);
		}
		private static object CreateInstance<Arg1T, Arg2T, Arg3T, Arg4T>(Type type, Arg1T arg1, Arg2T arg2, Arg3T arg3, Arg4T arg4, int argCount)
		{
			if (type == null) throw new ArgumentNullException("type");
			if (argCount < 1 || argCount > 3) throw new ArgumentOutOfRangeException("argCount");

			var signature = new ConstructorSignature(type, 
				typeof(Arg1T), argCount > 1 ? 
				typeof(Arg2T) : null, argCount > 2 ? 
				typeof(Arg3T) : argCount > 3 ? 
				typeof(Arg4T) : null);
#if !NETSTANDARD
			var typeInfo = type;
			var constructors = typeInfo.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#else
			var typeInfo = type.GetTypeInfo();
			var constructors = typeInfo.DeclaredConstructors.ToList();
#endif
			var constructor = default(Delegate);
			lock (CustomConstructorCache)
			{
				if (CustomConstructorCache.TryGetValue(signature, out constructor) == false)
				{
					var foundCtr = default(ConstructorInfo);

					foreach (var constructorInfo in constructors)
					{
						var ctrParams = constructorInfo.GetParameters();
						if (ctrParams.Length != argCount)
							continue;
						if (argCount > 0 && IsAssignableFrom(typeof(Arg1T), ctrParams[0].ParameterType) == false)
							continue;
						if (argCount > 1 && IsAssignableFrom(typeof(Arg2T), ctrParams[1].ParameterType) == false)
							continue;
						if (argCount > 2 && IsAssignableFrom(typeof(Arg3T), ctrParams[2].ParameterType) == false)
							continue;
						if (argCount > 3 && IsAssignableFrom(typeof(Arg4T), ctrParams[3].ParameterType) == false)
							continue;

						foundCtr = constructorInfo;
						break;
					}

					if (foundCtr != null)
					{<commit_msg>fixed error in type activator parameters binding (now more specific types binds successfully)<commit_after>﻿/*
	Copyright (c) 2016 <NAME>
	
	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

	License: https://opensource.org/licenses/MIT
*/

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

// ReSharper disable once CheckNamespace
namespace System
{
	public static class TypeActivator
	{
		private struct ConstructorSignature : IEquatable<ConstructorSignature>
		{
			private readonly Type type;
			private readonly Type arg1Type;
			private readonly Type arg2Type;
			private readonly Type arg3Type;
			private readonly Type arg4Type;

			public ConstructorSignature(Type type, Type arg1Type, Type arg2Type = null, Type arg3Type = null, Type arg4Type = null)
			{
				if (type == null) throw new ArgumentNullException("type");
				if (arg1Type == null) throw new ArgumentNullException("arg1Type");

				this.type = type;
				this.arg1Type = arg1Type;
				this.arg2Type = arg2Type ?? typeof(void);
				this.arg3Type = arg3Type ?? typeof(void);
				this.arg4Type = arg4Type ?? typeof(void);
			}

			public override int GetHashCode()
			{
				return unchecked(this.type.GetHashCode() + this.arg1Type.GetHashCode() + this.arg2Type.GetHashCode() + this.arg3Type.GetHashCode() + this.arg4Type.GetHashCode());
			}
			public override bool Equals(object obj)
			{
				if (obj == null || !(obj is ConstructorSignature))
					return false;
				return this.Equals((ConstructorSignature)obj);
			}
			public bool Equals(ConstructorSignature other)
			{
				return this.type == other.type && this.arg1Type == other.arg1Type && this.arg2Type == other.arg2Type && this.arg3Type == other.arg3Type && this.arg4Type == other.arg4Type;
			}

			public override string ToString() { return string.Format("{0}({1}, {2}, {3}, {4})", this.type.Name, this.arg1Type.Name, this.arg2Type.Name, this.arg3Type.Name, this.arg4Type.Name); }
		}

		private static readonly Dictionary<Type, Func<object>> DefaultConstructorCache = new Dictionary<Type, Func<object>>();
		private static readonly Dictionary<ConstructorSignature, Delegate> CustomConstructorCache = new Dictionary<ConstructorSignature, Delegate>();
		private static readonly HashSet<string> ConstructorSubstitutionMembers = new HashSet<string>(new[] { "Empty", "Default", "Instance" }, StringComparer.OrdinalIgnoreCase);

#if !NETSTANDARD
		public static object CreateInstance(Type type)
		{
			return CreateInstance(type, forceCreate: false);
		}
		public static object CreateInstance(Type type, bool forceCreate)
#else
		public static object CreateInstance(Type type)
#endif
		{
			if (type == null) throw new ArgumentNullException("type");

			var constructorFn = default(Func<object>);
			lock (DefaultConstructorCache)
			{
				if (DefaultConstructorCache.TryGetValue(type, out constructorFn) == false)
				{
#if !NETSTANDARD
					var typeInfo = type;
					var constructors = typeInfo.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
					var publicEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && c.IsPublic && c.IsStatic == false);
					var privateEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && !c.IsPublic && c.IsStatic == false);
					var instanceField = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).FirstOrDefault(f =>
						ConstructorSubstitutionMembers.Contains(f.Name) &&
						type.IsAssignableFrom(f.FieldType)
					);
					var instanceProperty = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).FirstOrDefault(p =>
						ConstructorSubstitutionMembers.Contains(p.Name) &&
						type.IsAssignableFrom(p.PropertyType) &&
						p.CanRead && p.GetIndexParameters().Length == 0
					);
#else
					var typeInfo = type.GetTypeInfo();
					var constructors = typeInfo.DeclaredConstructors.ToList();
					var publicEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && c.IsPublic && c.IsStatic == false);
					var privateEmptyConstructor = constructors.SingleOrDefault(c => c.GetParameters().Length == 0 && c.IsPublic == false && c.IsStatic == false);
					var instanceField = type.GetRuntimeFields().FirstOrDefault(f =>
						f.IsStatic &&
						ConstructorSubstitutionMembers.Contains(f.Name) &&
						IsAssignableFrom(type, f.FieldType)
					);
					var instanceProperty = type.GetRuntimeProperties().FirstOrDefault(p =>
						p.GetMethod != null &&
						p.GetMethod.IsStatic &&
						ConstructorSubstitutionMembers.Contains(p.Name) &&
						IsAssignableFrom(type, p.PropertyType) &&
						p.GetIndexParameters().Length == 0
					);
#endif

					if (publicEmptyConstructor != null)
					{
						var createNewObjectExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.New(publicEmptyConstructor),
								typeof(object)
							)
						);

						constructorFn = createNewObjectExpr.Compile();
					}
					else if (instanceField != null)
					{
						var getInstanceFieldExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.Field(null, instanceField),
								typeof(object)
							)
						);
						constructorFn = getInstanceFieldExpr.Compile();
					}
					else if (instanceProperty != null)
					{
						var getInstancePropertyExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.Property(null, instanceProperty),
								typeof(object)
							)
						);
						constructorFn = getInstancePropertyExpr.Compile();
					}
					else if (privateEmptyConstructor != null)
					{
						var createNewObjectExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.New(privateEmptyConstructor),
								typeof(object)
							)
						);

						constructorFn = createNewObjectExpr.Compile();
					}
					else if (type.IsArray && type.GetArrayRank() == 1)
					{
						var elementType = type.GetElementType();
						Debug.Assert(elementType != null, "elementType != null");
						var createNewArrayExpr = Expression.Lambda<Func<object>>
						(
							Expression.Convert
							(
								Expression.Constant(Array.CreateInstance(elementType, 0)),
								typeof(object)
							)
						);

						constructorFn = createNewArrayExpr.Compile();
					}
					else if (typeInfo.IsValueType)
					{
						var createNewValueTypeExpr = Expression.Lambda<Func<object>>
						(
							Expression.Constant
							(
								Activator.CreateInstance(type),
								typeof(object)
							)
						);

						constructorFn = createNewValueTypeExpr.Compile();
					}

					DefaultConstructorCache[type] = constructorFn;
				}
			}

#if !NETSTANDARD
			if (constructorFn == null && forceCreate)
				return Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(type);
#endif
			if (constructorFn == null)
				throw new ArgumentException(string.Format("Type '{0}' does not contains default empty constructor.", type), "type");
			else
				return constructorFn();
		}
		public static object CreateInstance<Arg1T>(Type type, Arg1T arg1)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance<Arg1T, object, object, object>(type, arg1, null, null, null, 1);
		}
		public static object CreateInstance<Arg1T, Arg2T>(Type type, Arg1T arg1, Arg2T arg2)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance<Arg1T, Arg2T, object, object>(type, arg1, arg2, null, null, 2);
		}
		public static object CreateInstance<Arg1T, Arg2T, Arg3T>(Type type, Arg1T arg1, Arg2T arg2, Arg3T arg3)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance<Arg1T, Arg2T, Arg3T, object>(type, arg1, arg2, arg3, null, 3);
		}
		public static object CreateInstance<Arg1T, Arg2T, Arg3T, Arg4T>(Type type, Arg1T arg1, Arg2T arg2, Arg3T arg3, Arg4T arg4)
		{
			if (type == null) throw new ArgumentNullException("type");

			return CreateInstance(type, arg1, arg2, arg3, arg4, 4);
		}
		private static object CreateInstance<Arg1T, Arg2T, Arg3T, Arg4T>(Type type, Arg1T arg1, Arg2T arg2, Arg3T arg3, Arg4T arg4, int argCount)
		{
			if (type == null) throw new ArgumentNullException("type");
			if (argCount < 1 || argCount > 4) throw new ArgumentOutOfRangeException("argCount");

			var signature = new ConstructorSignature(type, 
				typeof(Arg1T), argCount > 1 ? 
				typeof(Arg2T) : null, argCount > 2 ? 
				typeof(Arg3T) : argCount > 3 ? 
				typeof(Arg4T) : null);
#if !NETSTANDARD
			var typeInfo = type;
			var constructors = typeInfo.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#else
			var typeInfo = type.GetTypeInfo();
			var constructors = typeInfo.DeclaredConstructors.ToList();
#endif
			var constructor = default(Delegate);
			lock (CustomConstructorCache)
			{
				if (CustomConstructorCache.TryGetValue(signature, out constructor) == false)
				{
					var foundCtr = default(ConstructorInfo);

					foreach (var constructorInfo in constructors)
					{
						var ctrParams = constructorInfo.GetParameters();
						if (ctrParams.Length != argCount)
							continue;
						if (argCount > 0 && IsAssignableFrom(ctrParams[0].ParameterType, typeof(Arg1T)) == false)
							continue;
						if (argCount > 1 && IsAssignableFrom(ctrParams[1].ParameterType, typeof(Arg2T)) == false)
							continue;
						if (argCount > 2 && IsAssignableFrom(ctrParams[2].ParameterType, typeof(Arg3T)) == false)
							continue;
						if (argCount > 3 && IsAssignableFrom(ctrParams[3].ParameterType, typeof(Arg4T)) == false)
							continue;

						foundCtr = constructorInfo;
						break;
					}

					if (foundCtr != null)
					{
{'fraction_non_alphanumeric': 0.11212607910058221, 'fraction_numerical': 0.013551495683597672, 'mean_word_length': 3.613336420467701, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 97, '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': '3192870', 'n_tokens_mistral': 7479, 'n_tokens_neox': 5737, 'n_words': 1354}