[NUI] Rebase develnui (DevelNUI only patches --> master) (#3910)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Internal / GenericMethodHelper.cs
1 // ***********************************************************************
2 // Copyright (c) 2015 Charlie Poole
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
23 #define PORTABLE
24 #define TIZEN
25 #define NUNIT_FRAMEWORK
26 #define NUNITLITE
27 #define NET_4_5
28 #define PARALLEL
29 using System;
30 using System.Collections.Generic;
31 using System.Reflection;
32 using NUnit.Compatibility;
33
34 namespace NUnit.Framework.Internal
35 {
36     /// <summary>
37     /// GenericMethodHelper is able to deduce the Type arguments for
38     /// a generic method from the actual arguments provided.
39     /// </summary>
40     public class GenericMethodHelper
41     {
42         /// <summary>
43         /// Construct a GenericMethodHelper for a method
44         /// </summary>
45         /// <param name="method">MethodInfo for the method to examine</param>
46         public GenericMethodHelper(MethodInfo method)
47         {
48             Guard.ArgumentValid(method.IsGenericMethod, "Specified method must be generic", "method");
49
50             Method = method;
51
52             TypeParms = Method.GetGenericArguments();
53             TypeArgs = new Type[TypeParms.Length];
54
55             var parms = Method.GetParameters();
56             ParmTypes = new Type[parms.Length];
57             for (int i = 0; i < parms.Length; i++)
58                 ParmTypes[i] = parms[i].ParameterType;
59         }
60
61         private MethodInfo Method { get; set; }
62
63         private Type[] TypeParms { get; set; }
64         private Type[] TypeArgs { get; set; }
65
66         private Type[] ParmTypes { get; set; }
67
68         /// <summary>
69         /// Return the type argments for the method, deducing them
70         /// from the arguments actually provided.
71         /// </summary>
72         /// <param name="argList">The arguments to the method</param>
73         /// <returns>An array of type arguments.</returns>
74         public Type[] GetTypeArguments(object[] argList)
75         {
76             Guard.ArgumentValid(argList.Length == ParmTypes.Length, "Supplied arguments do not match required method parameters", "argList");
77
78             for (int argIndex = 0; argIndex < ParmTypes.Length; argIndex++)
79             {
80                 var arg = argList[argIndex];
81
82                 if (arg != null)
83                 {
84                     Type argType = arg.GetType();
85                     TryApplyArgType(ParmTypes[argIndex], argType);
86                 }
87             }
88
89             return TypeArgs;
90         }
91
92         private void TryApplyArgType(Type parmType, Type argType)
93         {
94             if (parmType.IsGenericParameter)
95             {
96                 ApplyArgType(parmType, argType);
97             }
98             else if (parmType.GetTypeInfo().ContainsGenericParameters)
99             {
100                 var genericArgTypes = parmType.GetGenericArguments();
101
102                 if (argType.HasElementType)
103                 {
104                     ApplyArgType(genericArgTypes[0], argType.GetElementType());
105                 }
106                 else if (argType.GetTypeInfo().IsGenericType && IsAssignableToGenericType(argType, parmType))
107                 {
108                     Type[] argTypes = argType.GetGenericArguments();
109
110                     if (argTypes.Length == genericArgTypes.Length)
111                         for (int i = 0; i < genericArgTypes.Length; i++)
112                             TryApplyArgType(genericArgTypes[i], argTypes[i]);
113                 }
114             }
115         }
116
117         private void ApplyArgType(Type parmType, Type argType)
118         {
119             // Note: parmType must be generic parameter type - checked by caller
120 #if NETCF
121             var index = Array.IndexOf(TypeParms, parmType);
122 #else
123             var index = parmType.GenericParameterPosition;
124 #endif
125             TypeArgs[index] = TypeHelper.BestCommonType(TypeArgs[index], argType);
126         }
127
128         // Simulates IsAssignableTo generics
129         private bool IsAssignableToGenericType(Type givenType, Type genericType)
130         {
131             var interfaceTypes = givenType.GetInterfaces();
132
133             foreach (var iterator in interfaceTypes)
134             {
135                 if (iterator.GetTypeInfo().IsGenericType)
136                 {
137                     // The Type returned by GetGenericTyeDefinition may have the
138                     // FullName set to null, so we do our own comparison
139                     Type gtd = iterator.GetGenericTypeDefinition();
140                     if (gtd.Name == genericType.Name && gtd.Namespace == genericType.Namespace)
141                         return true;
142                 }
143             }
144
145             if (givenType.GetTypeInfo().IsGenericType)
146             {
147                 // The Type returned by GetGenericTyeDefinition may have the
148                 // FullName set to null, so we do our own comparison
149                 Type gtd = givenType.GetGenericTypeDefinition();
150                 if (gtd.Name == genericType.Name && gtd.Namespace == genericType.Namespace)
151                     return true;
152             }
153
154             Type baseType = givenType.GetTypeInfo().BaseType;
155             if (baseType == null)
156                 return false;
157
158             return IsAssignableToGenericType(baseType, genericType);
159         }
160     }
161 }