Merge pull request #1542 from ninjarobot/UriTemplateMatchException
[mono.git] / mcs / tools / linker / Mono.Linker.Steps / MarkStep.cs
1 //
2 // MarkStep.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2006 Jb Evain
8 // (C) 2007 Novell, Inc.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections;
32 using System.Linq;
33
34 using Mono.Cecil;
35 using Mono.Cecil.Cil;
36
37 namespace Mono.Linker.Steps {
38
39         public class MarkStep : IStep {
40
41                 protected LinkContext _context;
42                 protected Queue _methods;
43                 protected ArrayList _virtual_methods;
44
45                 public AnnotationStore Annotations {
46                         get { return _context.Annotations; }
47                 }
48
49                 public MarkStep ()
50                 {
51                         _methods = new Queue ();
52                         _virtual_methods = new ArrayList ();
53                 }
54
55                 public virtual void Process (LinkContext context)
56                 {
57                         _context = context;
58
59                         Initialize ();
60                         Process ();
61                 }
62
63                 void Initialize ()
64                 {
65                         foreach (AssemblyDefinition assembly in _context.GetAssemblies ())
66                                 InitializeAssembly (assembly);
67                 }
68
69                 protected virtual void InitializeAssembly (AssemblyDefinition assembly)
70                 {
71                         MarkAssembly (assembly);
72                         foreach (TypeDefinition type in assembly.MainModule.Types) {
73                                 if (!Annotations.IsMarked (type))
74                                         continue;
75
76                                 InitializeType (type);
77                         }
78                 }
79
80                 void InitializeType (TypeDefinition type)
81                 {
82                         MarkType (type);
83
84                         if (type.HasFields)
85                                 InitializeFields (type);
86                         if (type.HasMethods)
87                                 InitializeMethods (type.Methods);
88
89                         if (type.HasNestedTypes) {
90                                 foreach (var nested in type.NestedTypes) {
91                                         if (Annotations.IsMarked (nested))
92                                                 InitializeType (nested);
93                                 }
94                         }
95                 }
96
97                 void InitializeFields (TypeDefinition type)
98                 {
99                         foreach (FieldDefinition field in type.Fields)
100                                 if (Annotations.IsMarked (field))
101                                         MarkField (field);
102                 }
103
104                 void InitializeMethods (ICollection methods)
105                 {
106                         foreach (MethodDefinition method in methods)
107                                 if (Annotations.IsMarked (method))
108                                         EnqueueMethod (method);
109                 }
110
111                 void Process ()
112                 {
113                         if (QueueIsEmpty ())
114                                 throw new InvalidOperationException ("No entry methods");
115
116                         while (!QueueIsEmpty ()) {
117                                 ProcessQueue ();
118                                 ProcessVirtualMethods ();
119                         }
120                 }
121
122                 void ProcessQueue ()
123                 {
124                         while (!QueueIsEmpty ()) {
125                                 MethodDefinition method = (MethodDefinition) _methods.Dequeue ();
126                                 ProcessMethod (method);
127                         }
128                 }
129
130                 bool QueueIsEmpty ()
131                 {
132                         return _methods.Count == 0;
133                 }
134
135                 protected virtual void EnqueueMethod (MethodDefinition method)
136                 {
137                         _methods.Enqueue (method);
138                 }
139
140                 void ProcessVirtualMethods ()
141                 {
142                         foreach (MethodDefinition method in _virtual_methods)
143                                 ProcessVirtualMethod (method);
144                 }
145
146                 void ProcessVirtualMethod (MethodDefinition method)
147                 {
148                         IList overrides = Annotations.GetOverrides (method);
149                         if (overrides == null)
150                                 return;
151
152                         foreach (MethodDefinition @override in overrides)
153                                 ProcessOverride (@override);
154                 }
155
156                 void ProcessOverride (MethodDefinition method)
157                 {
158                         if (!Annotations.IsMarked (method.DeclaringType))
159                                 return;
160
161                         if (Annotations.IsProcessed (method))
162                                 return;
163
164                         if (Annotations.IsMarked (method))
165                                 return;
166
167                         MarkMethod (method);
168                         ProcessVirtualMethod (method);
169                 }
170
171                 void MarkMarshalSpec (IMarshalInfoProvider spec)
172                 {
173                         if (!spec.HasMarshalInfo)
174                                 return;
175
176                         var marshaler = spec.MarshalInfo as CustomMarshalInfo;
177                         if (marshaler == null)
178                                 return;
179
180                         MarkType (marshaler.ManagedType);
181                 }
182
183                 void MarkCustomAttributes (ICustomAttributeProvider provider)
184                 {
185                         if (!provider.HasCustomAttributes)
186                                 return;
187
188                         foreach (CustomAttribute ca in provider.CustomAttributes)
189                                 MarkCustomAttribute (ca);
190                 }
191
192                 protected virtual void MarkCustomAttribute (CustomAttribute ca)
193                 {
194                         MarkMethod (ca.Constructor);
195
196                         MarkCustomAttributeArguments (ca);
197
198                         TypeReference constructor_type = ca.Constructor.DeclaringType;
199                         TypeDefinition type = constructor_type.Resolve ();
200                         if (type == null)
201                                 throw new ResolutionException (constructor_type);
202
203                         MarkCustomAttributeProperties (ca, type);
204                         MarkCustomAttributeFields (ca, type);
205                 }
206
207                 void MarkCustomAttributeProperties (CustomAttribute ca, TypeDefinition attribute)
208                 {
209                         if (!ca.HasProperties)
210                                 return;
211
212                         foreach (var named_argument in ca.Properties) {
213                                 PropertyDefinition property = GetProperty (attribute, named_argument.Name);
214                                 if (property != null)
215                                         MarkMethod (property.SetMethod);
216
217                                 MarkIfType (named_argument.Argument);
218                         }
219                 }
220
221                 PropertyDefinition GetProperty (TypeDefinition type, string propertyname)
222                 {
223                         while (type != null) {
224                                 PropertyDefinition property = type.Properties.FirstOrDefault (p => p.Name == propertyname);
225                                 if (property != null)
226                                         return property;
227
228                                 type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
229                         }
230
231                         return null;
232                 }
233
234                 void MarkCustomAttributeFields (CustomAttribute ca, TypeDefinition attribute)
235                 {
236                         if (!ca.HasFields)
237                                 return;
238
239                         foreach (var named_argument in ca.Fields) {
240                                 FieldDefinition field = GetField (attribute, named_argument.Name);
241                                 if (field != null)
242                                         MarkField (field);
243
244                                 MarkIfType (named_argument.Argument);
245                         }
246                 }
247
248                 FieldDefinition GetField (TypeDefinition type, string fieldname)
249                 {
250                         while (type != null) {
251                                 FieldDefinition field = type.Fields.FirstOrDefault (f => f.Name == fieldname);
252                                 if (field != null)
253                                         return field;
254
255                                 type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
256                         }
257
258                         return null;
259                 }
260
261                 void MarkCustomAttributeArguments (CustomAttribute ca)
262                 {
263                         if (!ca.HasConstructorArguments)
264                                 return;
265
266                         foreach (var argument in ca.ConstructorArguments)
267                                 MarkIfType (argument);
268                 }
269
270                 void MarkIfType (CustomAttributeArgument argument)
271                 {
272                         var at = argument.Type;
273                         if (at.IsArray) {
274                                 var et = at.GetElementType ();
275                                 if (et.Namespace != "System" || et.Name != "Type")
276                                         return;
277
278                                 MarkType (et);
279                                 foreach (var cac in (CustomAttributeArgument[]) argument.Value)
280                                         MarkWithResolvedScope ((TypeReference) cac.Value);
281                         } else if (at.Namespace == "System" && at.Name == "Type") {
282                                 MarkType (argument.Type);
283                                 MarkWithResolvedScope ((TypeReference) argument.Value);
284                         }
285                 }
286
287                 // custom attributes encoding means it's possible to have a scope that will point into a PCL facade
288                 // even if we (just before saving) will resolve all type references (bug #26752)
289                 void MarkWithResolvedScope (TypeReference type)
290                 {
291                         // we cannot set the Scope of a TypeSpecification so there's no point in resolving it
292                         if ((type == null) || (type is TypeSpecification))
293                                 return;
294                         var td = type.Resolve ();
295                         if (td != null)
296                                 type.Scope = td.Scope;
297                         MarkType (type);
298                 }
299
300                 protected bool CheckProcessed (IMetadataTokenProvider provider)
301                 {
302                         if (Annotations.IsProcessed (provider))
303                                 return true;
304
305                         Annotations.Processed (provider);
306                         return false;
307                 }
308
309                 void MarkAssembly (AssemblyDefinition assembly)
310                 {
311                         if (CheckProcessed (assembly))
312                                 return;
313
314                         ProcessModule (assembly);
315
316                         MarkCustomAttributes (assembly);
317
318                         foreach (ModuleDefinition module in assembly.Modules)
319                                 MarkCustomAttributes (module);
320                 }
321
322                 void ProcessModule (AssemblyDefinition assembly)
323                 {
324                         // Pre-mark <Module> if there is any methods as they need to be executed 
325                         // at assembly load time
326                         foreach (TypeDefinition type in assembly.MainModule.Types)
327                         {
328                                 if (type.Name == "<Module>" && type.HasMethods)
329                                 {
330                                         MarkType (type);
331                                         break;
332                                 }
333                         }
334                 }
335
336                 protected void MarkField (FieldReference reference)
337                 {
338 //                      if (IgnoreScope (reference.DeclaringType.Scope))
339 //                              return;
340
341                         if (reference.DeclaringType is GenericInstanceType)
342                                 MarkType (reference.DeclaringType);
343
344                         FieldDefinition field = ResolveFieldDefinition (reference);
345
346                         if (field == null)
347                                 throw new ResolutionException (reference);
348
349                         if (CheckProcessed (field))
350                                 return;
351
352                         MarkType (field.DeclaringType);
353                         MarkType (field.FieldType);
354                         MarkCustomAttributes (field);
355                         MarkMarshalSpec (field);
356
357                         Annotations.Mark (field);
358                 }
359
360                 protected virtual bool IgnoreScope (IMetadataScope scope)
361                 {
362                         AssemblyDefinition assembly = ResolveAssembly (scope);
363                         return Annotations.GetAction (assembly) != AssemblyAction.Link;
364                 }
365
366                 FieldDefinition ResolveFieldDefinition (FieldReference field)
367                 {
368                         FieldDefinition fd = field as FieldDefinition;
369                         if (fd == null)
370                                 fd = field.Resolve ();
371
372                         return fd;
373                 }
374
375                 void MarkScope (IMetadataScope scope)
376                 {
377                         var provider = scope as IMetadataTokenProvider;
378                         if (provider == null)
379                                 return;
380
381                         Annotations.Mark (provider);
382                 }
383
384                 protected virtual void MarkSerializable (TypeDefinition type)
385                 {
386                         MarkDefaultConstructor (type);
387                         MarkMethodsIf (type.Methods, IsSpecialSerializationConstructorPredicate);
388                 }
389
390                 protected virtual TypeDefinition MarkType (TypeReference reference)
391                 {
392                         if (reference == null)
393                                 return null;
394
395                         reference = GetOriginalType (reference);
396
397                         if (reference is GenericParameter)
398                                 return null;
399
400 //                      if (IgnoreScope (reference.Scope))
401 //                              return;
402
403                         TypeDefinition type = ResolveTypeDefinition (reference);
404
405                         if (type == null)
406                                 throw new ResolutionException (reference);
407
408                         if (CheckProcessed (type))
409                                 return null;
410
411                         MarkScope (type.Scope);
412                         MarkType (type.BaseType);
413                         MarkType (type.DeclaringType);
414                         MarkCustomAttributes (type);
415
416                         if (IsMulticastDelegate (type)) {
417                                 MarkMethodCollection (type.Methods);
418                         }
419
420                         if (IsSerializable (type))
421                                 MarkSerializable (type);
422
423                         MarkTypeSpecialCustomAttributes (type);
424
425                         MarkGenericParameterProvider (type);
426
427                         // keep fields for value-types and for classes with LayoutKind.Sequential or Explicit
428                         if (type.IsValueType || !type.IsAutoLayout)
429                                 MarkFields (type, type.IsEnum);
430
431                         if (type.HasInterfaces) {
432                                 foreach (TypeReference iface in type.Interfaces)
433                                         MarkType (iface);
434                         }
435
436                         if (type.HasMethods) {
437                                 MarkMethodsIf (type.Methods, IsVirtualAndHasPreservedParent);
438                                 MarkMethodsIf (type.Methods, IsStaticConstructorPredicate);
439                         }
440
441                         Annotations.Mark (type);
442
443                         ApplyPreserveInfo (type);
444
445                         return type;
446                 }
447
448                 void MarkTypeSpecialCustomAttributes (TypeDefinition type)
449                 {
450                         if (!type.HasCustomAttributes)
451                                 return;
452
453                         foreach (CustomAttribute attribute in type.CustomAttributes) {
454                                 switch (attribute.Constructor.DeclaringType.FullName) {
455                                 case "System.Xml.Serialization.XmlSchemaProviderAttribute":
456                                         MarkXmlSchemaProvider (type, attribute);
457                                         break;
458                                 }
459                         }
460                 }
461
462                 void MarkMethodSpecialCustomAttributes (MethodDefinition method)
463                 {
464                         if (!method.HasCustomAttributes)
465                                 return;
466
467                         foreach (CustomAttribute attribute in method.CustomAttributes) {
468                                 switch (attribute.Constructor.DeclaringType.FullName) {
469                                 case "System.Web.Services.Protocols.SoapHeaderAttribute":
470                                         MarkSoapHeader (method, attribute);
471                                         break;
472                                 }
473                         }
474                 }
475
476                 void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute)
477                 {
478                         string method_name;
479                         if (!TryGetStringArgument (attribute, out method_name))
480                                 return;
481
482                         MarkNamedMethod (type, method_name);
483                 }
484
485                 static bool TryGetStringArgument (CustomAttribute attribute, out string argument)
486                 {
487                         argument = null;
488
489                         if (attribute.ConstructorArguments.Count < 1)
490                                 return false;
491
492                         argument = attribute.ConstructorArguments [0].Value as string;
493
494                         return argument != null;
495                 }
496
497                 protected void MarkNamedMethod (TypeDefinition type, string method_name)
498                 {
499                         if (!type.HasMethods)
500                                 return;
501
502                         foreach (MethodDefinition method in type.Methods) {
503                                 if (method.Name != method_name)
504                                         continue;
505
506                                 MarkMethod (method);
507                         }
508                 }
509
510                 void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute)
511                 {
512                         string member_name;
513                         if (!TryGetStringArgument (attribute, out member_name))
514                                 return;
515
516                         MarkNamedField (method.DeclaringType, member_name);
517                         MarkNamedProperty (method.DeclaringType, member_name);
518                 }
519
520                 void MarkNamedField (TypeDefinition type, string field_name)
521                 {
522                         if (!type.HasFields)
523                                 return;
524
525                         foreach (FieldDefinition field in type.Fields) {
526                                 if (field.Name != field_name)
527                                         continue;
528
529                                 MarkField (field);
530                         }
531                 }
532
533                 void MarkNamedProperty (TypeDefinition type, string property_name)
534                 {
535                         if (!type.HasProperties)
536                                 return;
537
538                         foreach (PropertyDefinition property in type.Properties) {
539                                 if (property.Name != property_name)
540                                         continue;
541
542                                 MarkMethod (property.GetMethod);
543                                 MarkMethod (property.SetMethod);
544                         }
545                 }
546
547                 void MarkGenericParameterProvider (IGenericParameterProvider provider)
548                 {
549                         if (!provider.HasGenericParameters)
550                                 return;
551
552                         foreach (GenericParameter parameter in provider.GenericParameters)
553                                 MarkGenericParameter (parameter);
554                 }
555
556                 void MarkGenericParameter (GenericParameter parameter)
557                 {
558                         MarkCustomAttributes (parameter);
559                         foreach (TypeReference constraint in parameter.Constraints)
560                                 MarkType (constraint);
561                 }
562
563                 bool IsVirtualAndHasPreservedParent (MethodDefinition method)
564                 {
565                         if (!method.IsVirtual)
566                                 return false;
567
568                         var base_list = Annotations.GetBaseMethods (method);
569                         if (base_list == null)
570                                 return false;
571
572                         foreach (MethodDefinition @base in base_list) {
573                                 if (IgnoreScope (@base.DeclaringType.Scope))
574                                         return true;
575
576                                 if (IsVirtualAndHasPreservedParent (@base))
577                                         return true;
578                         }
579
580                         return false;
581                 }
582
583                 static MethodPredicate IsSpecialSerializationConstructorPredicate = new MethodPredicate (IsSpecialSerializationConstructor);
584
585                 static bool IsSpecialSerializationConstructor (MethodDefinition method)
586                 {
587                         if (!IsConstructor (method))
588                                 return false;
589
590                         var parameters = method.Parameters;
591                         if (parameters.Count != 2)
592                                 return false;
593
594                         return parameters [0].ParameterType.Name == "SerializationInfo" &&
595                                 parameters [1].ParameterType.Name == "StreamingContext";
596                 }
597
598                 delegate bool MethodPredicate (MethodDefinition method);
599
600                 void MarkMethodsIf (ICollection methods, MethodPredicate predicate)
601                 {
602                         foreach (MethodDefinition method in methods)
603                                 if (predicate (method))
604                                         MarkMethod (method);
605                 }
606
607                 static MethodPredicate IsDefaultConstructorPredicate = new MethodPredicate (IsDefaultConstructor);
608
609                 static bool IsDefaultConstructor (MethodDefinition method)
610                 {
611                         return IsConstructor (method) && !method.HasParameters;
612                 }
613
614                 static bool IsConstructor (MethodDefinition method)
615                 {
616                         return method.IsConstructor && !method.IsStatic;
617                 }
618
619                 protected void MarkDefaultConstructor (TypeDefinition type)
620                 {
621                         if ((type == null) || !type.HasMethods)
622                                 return;
623
624                         MarkMethodsIf (type.Methods, IsDefaultConstructorPredicate);
625                 }
626
627                 static MethodPredicate IsStaticConstructorPredicate = new MethodPredicate (IsStaticConstructor);
628
629                 static bool IsStaticConstructor (MethodDefinition method)
630                 {
631                         return method.IsConstructor && method.IsStatic;
632                 }
633
634                 static bool IsSerializable (TypeDefinition td)
635                 {
636                         return (td.Attributes & TypeAttributes.Serializable) != 0;
637                 }
638
639                 static bool IsMulticastDelegate (TypeDefinition td)
640                 {
641                         return td.BaseType != null && td.BaseType.FullName == "System.MulticastDelegate";
642                 }
643
644                 protected TypeDefinition ResolveTypeDefinition (TypeReference type)
645                 {
646                         TypeDefinition td = type as TypeDefinition;
647                         if (td == null)
648                                 td = type.Resolve ();
649
650                         return td;
651                 }
652
653                 protected TypeReference GetOriginalType (TypeReference type)
654                 {
655                         while (type is TypeSpecification) {
656                                 GenericInstanceType git = type as GenericInstanceType;
657                                 if (git != null)
658                                         MarkGenericArguments (git);
659
660                                 var mod = type as IModifierType;
661                                 if (mod != null)
662                                         MarkModifierType (mod);
663
664                                 type = ((TypeSpecification) type).ElementType;
665                         }
666
667                         return type;
668                 }
669
670                 void MarkModifierType (IModifierType mod)
671                 {
672                         MarkType (mod.ModifierType);
673                 }
674
675                 void MarkGenericArguments (IGenericInstance instance)
676                 {
677                         foreach (TypeReference argument in instance.GenericArguments)
678                                 MarkType (argument);
679
680                         MarkGenericArgumentConstructors (instance);
681                 }
682
683                 void MarkGenericArgumentConstructors (IGenericInstance instance)
684                 {
685                         var arguments = instance.GenericArguments;
686
687                         var generic_element = GetGenericProviderFromInstance (instance);
688                         if (generic_element == null)
689                                 return;
690
691                         var parameters = generic_element.GenericParameters;
692
693                         if (arguments.Count != parameters.Count)
694                                 return;
695
696                         for (int i = 0; i < arguments.Count; i++) {
697                                 var argument = arguments [i];
698                                 var parameter = parameters [i];
699
700                                 if (!parameter.HasDefaultConstructorConstraint)
701                                         continue;
702
703                                 var argument_definition = ResolveTypeDefinition (argument);
704                                 if (argument_definition == null)
705                                         continue;
706
707                                 MarkMethodsIf (argument_definition.Methods, ctor => !ctor.IsStatic && !ctor.HasParameters);
708                         }
709                 }
710
711                 IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance)
712                 {
713                         var method = instance as GenericInstanceMethod;
714                         if (method != null)
715                                 return ResolveMethodDefinition (method.ElementMethod);
716
717                         var type = instance as GenericInstanceType;
718                         if (type != null)
719                                 return ResolveTypeDefinition (type.ElementType);
720
721                         return null;
722                 }
723
724                 void ApplyPreserveInfo (TypeDefinition type)
725                 {
726                         ApplyPreserveMethods (type);
727
728                         if (!Annotations.IsPreserved (type))
729                                 return;
730
731                         switch (Annotations.GetPreserve (type)) {
732                         case TypePreserve.All:
733                                 MarkFields (type, true);
734                                 MarkMethods (type);
735                                 break;
736                         case TypePreserve.Fields:
737                                 MarkFields (type, true);
738                                 break;
739                         case TypePreserve.Methods:
740                                 MarkMethods (type);
741                                 break;
742                         }
743                 }
744
745                 void ApplyPreserveMethods (TypeDefinition type)
746                 {
747                         var list = Annotations.GetPreservedMethods (type);
748                         if (list == null)
749                                 return;
750
751                         MarkMethodCollection (list);
752                 }
753
754                 void ApplyPreserveMethods (MethodDefinition method)
755                 {
756                         var list = Annotations.GetPreservedMethods (method);
757                         if (list == null)
758                                 return;
759
760                         MarkMethodCollection (list);
761                 }
762
763                 protected void MarkFields (TypeDefinition type, bool includeStatic)
764                 {
765                         if (!type.HasFields)
766                                 return;
767
768                         foreach (FieldDefinition field in type.Fields) {
769                                 if (!includeStatic && field.IsStatic)
770                                         continue;
771                                 MarkField (field);
772                         }
773                 }
774
775                 protected virtual void MarkMethods (TypeDefinition type)
776                 {
777                         if (type.HasMethods)
778                                 MarkMethodCollection (type.Methods);
779                 }
780
781                 void MarkMethodCollection (IEnumerable methods)
782                 {
783                         foreach (MethodDefinition method in methods)
784                                 MarkMethod (method);
785                 }
786
787                 protected virtual MethodDefinition MarkMethod (MethodReference reference)
788                 {
789                         reference = GetOriginalMethod (reference);
790
791                         if (reference.DeclaringType is ArrayType)
792                                 return null;
793
794                         if (reference.DeclaringType is GenericInstanceType)
795                                 MarkType (reference.DeclaringType);
796
797 //                      if (IgnoreScope (reference.DeclaringType.Scope))
798 //                              return;
799
800                         MethodDefinition method = ResolveMethodDefinition (reference);
801
802                         if (method == null)
803                                 throw new ResolutionException (reference);
804
805                         if (Annotations.GetAction (method) == MethodAction.Nothing)
806                                 Annotations.SetAction (method, MethodAction.Parse);
807
808                         EnqueueMethod (method);
809                         return method;
810                 }
811
812                 AssemblyDefinition ResolveAssembly (IMetadataScope scope)
813                 {
814                         AssemblyDefinition assembly = _context.Resolve (scope);
815                         MarkAssembly (assembly);
816                         return assembly;
817                 }
818
819                 protected MethodReference GetOriginalMethod (MethodReference method)
820                 {
821                         while (method is MethodSpecification) {
822                                 GenericInstanceMethod gim = method as GenericInstanceMethod;
823                                 if (gim != null)
824                                         MarkGenericArguments (gim);
825
826                                 method = ((MethodSpecification) method).ElementMethod;
827                         }
828
829                         return method;
830                 }
831
832                 MethodDefinition ResolveMethodDefinition (MethodReference method)
833                 {
834                         MethodDefinition md = method as MethodDefinition;
835                         if (md == null)
836                                 md = method.Resolve ();
837
838                         return md;
839                 }
840
841                 protected virtual void ProcessMethod (MethodDefinition method)
842                 {
843                         if (CheckProcessed (method))
844                                 return;
845
846                         MarkType (method.DeclaringType);
847                         MarkCustomAttributes (method);
848
849                         MarkGenericParameterProvider (method);
850
851                         if (IsPropertyMethod (method))
852                                 MarkProperty (GetProperty (method));
853                         else if (IsEventMethod (method))
854                                 MarkEvent (GetEvent (method));
855
856                         if (method.HasParameters) {
857                                 foreach (ParameterDefinition pd in method.Parameters) {
858                                         MarkType (pd.ParameterType);
859                                         MarkCustomAttributes (pd);
860                                         MarkMarshalSpec (pd);
861                                 }
862                         }
863
864                         if (method.HasOverrides) {
865                                 foreach (MethodReference ov in method.Overrides)
866                                         MarkMethod (ov);
867                         }
868
869                         MarkMethodSpecialCustomAttributes (method);
870
871                         if (method.IsVirtual)
872                                 _virtual_methods.Add (method);
873
874                         MarkBaseMethods (method);
875
876                         MarkType (method.ReturnType);
877                         MarkCustomAttributes (method.MethodReturnType);
878                         MarkMarshalSpec (method.MethodReturnType);
879
880                         if (ShouldParseMethodBody (method))
881                                 MarkMethodBody (method.Body);
882
883                         Annotations.Mark (method);
884
885                         ApplyPreserveMethods (method);
886                 }
887
888                 void MarkBaseMethods (MethodDefinition method)
889                 {
890                         IList base_methods = Annotations.GetBaseMethods (method);
891                         if (base_methods == null)
892                                 return;
893
894                         foreach (MethodDefinition base_method in base_methods) {
895                                 if (base_method.DeclaringType.IsInterface && !method.DeclaringType.IsInterface)
896                                         continue;
897
898                                 MarkMethod (base_method);
899                                 MarkBaseMethods (base_method);
900                         }
901                 }
902
903                 bool ShouldParseMethodBody (MethodDefinition method)
904                 {
905                         if (!method.HasBody)
906                                 return false;
907
908                         AssemblyDefinition assembly = ResolveAssembly (method.DeclaringType.Scope);
909                         return (Annotations.GetAction (method) == MethodAction.ForceParse ||
910                                 (Annotations.GetAction (assembly) == AssemblyAction.Link && Annotations.GetAction (method) == MethodAction.Parse));
911                 }
912
913                 static internal bool IsPropertyMethod (MethodDefinition md)
914                 {
915                         return (md.SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0 ||
916                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0;
917                 }
918
919                 static bool IsEventMethod (MethodDefinition md)
920                 {
921                         return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 ||
922                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0 ||
923                                 (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0;
924                 }
925
926                 static internal PropertyDefinition GetProperty (MethodDefinition md)
927                 {
928                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
929                         foreach (PropertyDefinition prop in declaringType.Properties)
930                                 if (prop.GetMethod == md || prop.SetMethod == md)
931                                         return prop;
932
933                         return null;
934                 }
935
936                 static EventDefinition GetEvent (MethodDefinition md)
937                 {
938                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
939                         foreach (EventDefinition evt in declaringType.Events)
940                                 if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md)
941                                         return evt;
942
943                         return null;
944                 }
945
946                 protected void MarkProperty (PropertyDefinition prop)
947                 {
948                         MarkCustomAttributes (prop);
949                 }
950
951                 protected void MarkEvent (EventDefinition evt)
952                 {
953                         MarkCustomAttributes (evt);
954                         MarkMethodIfNotNull (evt.AddMethod);
955                         MarkMethodIfNotNull (evt.InvokeMethod);
956                         MarkMethodIfNotNull (evt.RemoveMethod);
957                 }
958
959                 void MarkMethodIfNotNull (MethodReference method)
960                 {
961                         if (method == null)
962                                 return;
963
964                         MarkMethod (method);
965                 }
966
967                 protected virtual void MarkMethodBody (MethodBody body)
968                 {
969                         foreach (VariableDefinition var in body.Variables)
970                                 MarkType (var.VariableType);
971
972                         foreach (ExceptionHandler eh in body.ExceptionHandlers)
973                                 if (eh.HandlerType == ExceptionHandlerType.Catch)
974                                         MarkType (eh.CatchType);
975
976                         foreach (Instruction instruction in body.Instructions)
977                                 MarkInstruction (instruction);
978                 }
979
980                 protected virtual void MarkInstruction (Instruction instruction)
981                 {
982                         switch (instruction.OpCode.OperandType) {
983                         case OperandType.InlineField:
984                                 MarkField ((FieldReference) instruction.Operand);
985                                 break;
986                         case OperandType.InlineMethod:
987                                 MarkMethod ((MethodReference) instruction.Operand);
988                                 break;
989                         case OperandType.InlineTok:
990                                 object token = instruction.Operand;
991                                 if (token is TypeReference)
992                                         MarkType ((TypeReference) token);
993                                 else if (token is MethodReference)
994                                         MarkMethod ((MethodReference) token);
995                                 else
996                                         MarkField ((FieldReference) token);
997                                 break;
998                         case OperandType.InlineType:
999                                 MarkType ((TypeReference) instruction.Operand);
1000                                 break;
1001                         default:
1002                                 break;
1003                         }
1004                 }
1005         }
1006 }