5 // Jb Evain (jbevain@novell.com)
7 // (C) 2009 Novell, Inc.
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.Collections.Generic;
35 namespace Mono.Linker.Steps {
37 public class TypeMapStep : BaseStep {
39 protected override void ProcessAssembly (AssemblyDefinition assembly)
41 foreach (TypeDefinition type in assembly.MainModule.Types)
45 protected virtual void MapType (TypeDefinition type)
47 MapVirtualMethods (type);
48 MapInterfaceMethodsInTypeHierarchy (type);
50 if (!type.HasNestedTypes)
53 foreach (var nested in type.NestedTypes)
57 void MapInterfaceMethodsInTypeHierarchy (TypeDefinition type)
59 if (!type.HasInterfaces)
62 foreach (TypeReference @interface in type.Interfaces) {
63 var iface = @interface.Resolve ();
64 if (iface == null || !iface.HasMethods)
67 foreach (MethodDefinition method in iface.Methods) {
68 if (TryMatchMethod (type, method) != null)
71 var @base = GetBaseMethodInTypeHierarchy (type, method);
75 Annotations.AddPreservedMethod (type, @base);
80 void MapVirtualMethods (TypeDefinition type)
85 foreach (MethodDefinition method in type.Methods) {
86 if (!method.IsVirtual)
89 MapVirtualMethod (method);
91 if (method.HasOverrides)
92 MapOverrides (method);
96 void MapVirtualMethod (MethodDefinition method)
98 MapVirtualBaseMethod (method);
99 MapVirtualInterfaceMethod (method);
102 void MapVirtualBaseMethod (MethodDefinition method)
104 MethodDefinition @base = GetBaseMethodInTypeHierarchy (method);
108 AnnotateMethods (@base, method);
111 void MapVirtualInterfaceMethod (MethodDefinition method)
113 foreach (MethodDefinition @base in GetBaseMethodsInInterfaceHierarchy (method))
114 AnnotateMethods (@base, method);
117 void MapOverrides (MethodDefinition method)
119 foreach (MethodReference override_ref in method.Overrides) {
120 MethodDefinition @override = override_ref.Resolve ();
121 if (@override == null)
124 AnnotateMethods (@override, method);
128 void AnnotateMethods (MethodDefinition @base, MethodDefinition @override)
130 Annotations.AddBaseMethod (@override, @base);
131 Annotations.AddOverride (@base, @override);
134 static MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method)
136 return GetBaseMethodInTypeHierarchy (method.DeclaringType, method);
139 static MethodDefinition GetBaseMethodInTypeHierarchy (TypeDefinition type, MethodDefinition method)
141 TypeDefinition @base = GetBaseType (type);
142 while (@base != null) {
143 MethodDefinition base_method = TryMatchMethod (@base, method);
144 if (base_method != null)
147 @base = GetBaseType (@base);
153 static IEnumerable<MethodDefinition> GetBaseMethodsInInterfaceHierarchy (MethodDefinition method)
155 return GetBaseMethodsInInterfaceHierarchy (method.DeclaringType, method);
158 static IEnumerable<MethodDefinition> GetBaseMethodsInInterfaceHierarchy (TypeDefinition type, MethodDefinition method)
160 if (!type.HasInterfaces)
163 foreach (TypeReference interface_ref in type.Interfaces) {
164 TypeDefinition @interface = interface_ref.Resolve ();
165 if (@interface == null)
168 MethodDefinition base_method = TryMatchMethod (@interface, method);
169 if (base_method != null)
170 yield return base_method;
172 foreach (MethodDefinition @base in GetBaseMethodsInInterfaceHierarchy (@interface, method))
177 static MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition method)
179 if (!type.HasMethods)
182 foreach (MethodDefinition candidate in type.Methods)
183 if (MethodMatch (candidate, method))
189 static bool MethodMatch (MethodDefinition candidate, MethodDefinition method)
191 if (!candidate.IsVirtual)
194 if (candidate.Name != method.Name)
197 if (!TypeMatch (candidate.ReturnType, method.ReturnType))
200 if (candidate.Parameters.Count != method.Parameters.Count)
203 for (int i = 0; i < candidate.Parameters.Count; i++)
204 if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType))
210 static bool TypeMatch (IModifierType a, IModifierType b)
212 if (!TypeMatch (a.ModifierType, b.ModifierType))
215 return TypeMatch (a.ElementType, b.ElementType);
218 static bool TypeMatch (TypeSpecification a, TypeSpecification b)
220 if (a is GenericInstanceType)
221 return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b);
223 if (a is IModifierType)
224 return TypeMatch ((IModifierType) a, (IModifierType) b);
226 return TypeMatch (a.ElementType, b.ElementType);
229 static bool TypeMatch (GenericInstanceType a, GenericInstanceType b)
231 if (!TypeMatch (a.ElementType, b.ElementType))
234 if (a.GenericArguments.Count != b.GenericArguments.Count)
237 if (a.GenericArguments.Count == 0)
240 for (int i = 0; i < a.GenericArguments.Count; i++)
241 if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i]))
247 static bool TypeMatch (TypeReference a, TypeReference b)
249 if (a is GenericParameter)
252 if (a is TypeSpecification || b is TypeSpecification) {
253 if (a.GetType () != b.GetType ())
256 return TypeMatch ((TypeSpecification) a, (TypeSpecification) b);
259 return a.FullName == b.FullName;
262 static TypeDefinition GetBaseType (TypeDefinition type)
264 if (type == null || type.BaseType == null)
267 return type.BaseType.Resolve ();