[interp] Fall back to old implementation when calling on proxy
[mono-project.git] / mcs / tools / corcompare / Util.cs
blob107c721d9e47e45741981fff2983a99397634040
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using Mono.Cecil;
6 namespace Mono.ApiTools {
8 class TypeHelper {
10 public TypeHelper (bool ignoreResolutionErrors, bool ignoreInheritedInterfaces)
12 IgnoreResolutionErrors = ignoreResolutionErrors;
13 IgnoreInheritedInterfaces = ignoreInheritedInterfaces;
16 public bool IgnoreResolutionErrors { get; }
18 public bool IgnoreInheritedInterfaces { get; }
20 public AssemblyResolver Resolver { get; } = new AssemblyResolver();
22 internal bool TryResolve (CustomAttribute attribute)
24 if (attribute == null)
25 throw new ArgumentNullException (nameof (attribute));
27 try {
28 var has = attribute.HasProperties;
29 return true;
30 } catch (AssemblyResolutionException) when (IgnoreResolutionErrors) {
31 return false;
35 internal bool IsPublic (TypeReference typeref)
37 if (typeref == null)
38 throw new ArgumentNullException ("typeref");
40 try {
41 var td = typeref.Resolve ();
42 if (td == null)
43 return false;
45 return td.IsPublic || (td.IsNestedPublic && IsPublic (td.DeclaringType));
46 } catch (AssemblyResolutionException) when (IgnoreResolutionErrors) {
47 return true;
51 internal bool IsDelegate (TypeReference typeref)
53 return IsDerivedFrom (typeref, "System.MulticastDelegate");
56 internal bool IsDerivedFrom (TypeReference type, string derivedFrom)
58 bool first = true;
59 foreach (var def in WalkHierarchy (type)) {
60 if (first) {
61 first = false;
62 continue;
65 if (def.FullName == derivedFrom)
66 return true;
69 return false;
72 internal IEnumerable<TypeDefinition> WalkHierarchy (TypeReference type)
74 for (var def = type.Resolve (); def != null; def = GetBaseType (def))
75 yield return def;
78 internal IEnumerable<TypeReference> GetInterfaces (TypeReference type)
80 var ifaces = new Dictionary<string, TypeReference> ();
82 foreach (var def in WalkHierarchy (type)) {
83 foreach (var iface in def.Interfaces)
84 ifaces [iface.InterfaceType.FullName] = iface.InterfaceType;
85 if (IgnoreInheritedInterfaces)
86 break;
89 return ifaces.Values;
92 internal TypeDefinition GetBaseType (TypeDefinition child)
94 if (child.BaseType == null)
95 return null;
97 try {
98 return child.BaseType.Resolve ();
99 } catch (AssemblyResolutionException) when (IgnoreResolutionErrors) {
100 return null;
104 internal MethodDefinition GetMethod (MethodReference method)
106 if (method == null)
107 throw new ArgumentNullException (nameof (method));
109 try {
110 return method.Resolve ();
111 } catch (AssemblyResolutionException) when (IgnoreResolutionErrors) {
112 return null;
116 internal bool IsPublic (CustomAttribute att)
118 return IsPublic (att.AttributeType);
121 internal string GetFullName (CustomAttribute att)
123 return att.AttributeType.FullName;
126 internal TypeDefinition GetTypeDefinition (CustomAttribute att)
128 return att.AttributeType.Resolve ();
131 bool IsOverride (MethodDefinition method)
133 return method.IsVirtual && !method.IsNewSlot;
136 public MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method)
138 if (!IsOverride (method))
139 return method;
141 var @base = GetBaseType (method.DeclaringType);
142 while (@base != null) {
143 MethodDefinition base_method = TryMatchMethod (@base.Resolve (), method);
144 if (base_method != null)
145 return GetBaseMethodInTypeHierarchy (base_method) ?? base_method;
147 @base = GetBaseType (@base);
150 return method;
153 MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition method)
155 if (!type.HasMethods)
156 return null;
158 foreach (MethodDefinition candidate in type.Methods)
159 if (MethodMatch (candidate, method))
160 return candidate;
162 return null;
165 bool MethodMatch (MethodDefinition candidate, MethodDefinition method)
167 if (!candidate.IsVirtual)
168 return false;
170 if (candidate.Name != method.Name)
171 return false;
173 if (!TypeMatch (candidate.ReturnType, method.ReturnType))
174 return false;
176 if (candidate.Parameters.Count != method.Parameters.Count)
177 return false;
179 for (int i = 0; i < candidate.Parameters.Count; i++)
180 if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType))
181 return false;
183 return true;
186 public bool TypeMatch (IModifierType a, IModifierType b)
188 if (!TypeMatch (a.ModifierType, b.ModifierType))
189 return false;
191 return TypeMatch (a.ElementType, b.ElementType);
194 public bool TypeMatch (TypeSpecification a, TypeSpecification b)
196 if (a is GenericInstanceType)
197 return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b);
199 if (a is IModifierType)
200 return TypeMatch ((IModifierType) a, (IModifierType) b);
202 return TypeMatch (a.ElementType, b.ElementType);
205 public bool TypeMatch (GenericInstanceType a, GenericInstanceType b)
207 if (!TypeMatch (a.ElementType, b.ElementType))
208 return false;
210 if (a.GenericArguments.Count != b.GenericArguments.Count)
211 return false;
213 if (a.GenericArguments.Count == 0)
214 return true;
216 for (int i = 0; i < a.GenericArguments.Count; i++)
217 if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i]))
218 return false;
220 return true;
223 public bool TypeMatch (TypeReference a, TypeReference b)
225 if (a is GenericParameter)
226 return true;
228 if (a is TypeSpecification || b is TypeSpecification) {
229 if (a.GetType () != b.GetType ())
230 return false;
232 return TypeMatch ((TypeSpecification) a, (TypeSpecification) b);
235 return a.FullName == b.FullName;