Merge pull request #963 from kebby/master
[mono.git] / mcs / tools / tuner / Mono.Tuner / Dispatcher.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4
5 using Mono.Linker;
6 using Mono.Linker.Steps;
7
8 using Mono.Cecil;
9
10 namespace Mono.Tuner {
11
12         [Flags]
13         public enum SubStepTargets {
14                 None = 0,
15
16                 Assembly = 1,
17                 Type = 2,
18                 Field = 4,
19                 Method = 8,
20                 Property = 16,
21                 Event = 32,
22         }
23
24         public interface ISubStep {
25
26                 SubStepTargets Targets { get; }
27
28                 void Initialize (LinkContext context);
29                 bool IsActiveFor (AssemblyDefinition assembly);
30
31                 void ProcessAssembly (AssemblyDefinition assembly);
32                 void ProcessType (TypeDefinition type);
33                 void ProcessField (FieldDefinition field);
34                 void ProcessMethod (MethodDefinition method);
35                 void ProcessProperty (PropertyDefinition property);
36                 void ProcessEvent (EventDefinition @event);
37         }
38
39         public abstract class BaseSubStep : ISubStep {
40
41                 protected LinkContext context;
42
43                 public AnnotationStore Annotations {
44                         get { return context.Annotations; }
45                 }
46
47                 public abstract SubStepTargets Targets { get; }
48
49                 public virtual void Initialize (LinkContext context)
50                 {
51                         this.context = context;
52                 }
53
54                 public virtual bool IsActiveFor (AssemblyDefinition assembly)
55                 {
56                         return true;
57                 }
58
59                 public virtual void ProcessAssembly (AssemblyDefinition assembly)
60                 {
61                 }
62
63                 public virtual void ProcessType (TypeDefinition type)
64                 {
65                 }
66
67                 public virtual void ProcessField (FieldDefinition field)
68                 {
69                 }
70
71                 public virtual void ProcessMethod (MethodDefinition method)
72                 {
73                 }
74
75                 public virtual void ProcessProperty (PropertyDefinition property)
76                 {
77                 }
78
79                 public virtual void ProcessEvent (EventDefinition @event)
80                 {
81                 }
82         }
83
84         public class SubStepDispatcher : IStep, IEnumerable<ISubStep> {
85
86                 List<ISubStep> substeps = new List<ISubStep> ();
87
88                 List<ISubStep> on_assemblies;
89                 List<ISubStep> on_types;
90                 List<ISubStep> on_fields;
91                 List<ISubStep> on_methods;
92                 List<ISubStep> on_properties;
93                 List<ISubStep> on_events;
94
95                 public void Add (ISubStep substep)
96                 {
97                         substeps.Add (substep);
98                 }
99
100                 public void Process (LinkContext context)
101                 {
102                         InitializeSubSteps (context);
103
104                         BrowseAssemblies (context.GetAssemblies ());
105                 }
106
107                 static bool HasSubSteps (List<ISubStep> substeps)
108                 {
109                         return substeps != null && substeps.Count > 0;
110                 }
111
112                 void BrowseAssemblies (IEnumerable<AssemblyDefinition> assemblies)
113                 {
114                         foreach (var assembly in assemblies) {
115                                 CategorizeSubSteps (assembly);
116
117                                 if (HasSubSteps (on_assemblies))
118                                         DispatchAssembly (assembly);
119
120                                 if (!ShouldDispatchTypes ())
121                                         continue;
122
123                                 BrowseTypes (assembly.MainModule.Types);
124                         }
125                 }
126
127                 bool ShouldDispatchTypes ()
128                 {
129                         return HasSubSteps (on_types)
130                                 || HasSubSteps (on_fields)
131                                 || HasSubSteps (on_methods)
132                                 || HasSubSteps (on_properties)
133                                 || HasSubSteps (on_events);
134                 }
135
136                 void BrowseTypes (ICollection types)
137                 {
138                         foreach (TypeDefinition type in types) {
139                                 DispatchType (type);
140
141                                 if (type.HasFields && HasSubSteps (on_fields))
142                                         BrowseFields (type.Fields);
143
144                                 if (type.HasMethods && HasSubSteps (on_methods))
145                                         BrowseMethods (type.Methods);
146
147                                 if (type.HasProperties && HasSubSteps (on_properties))
148                                         BrowseProperties (type.Properties);
149
150                                 if (type.HasEvents && HasSubSteps (on_events))
151                                         BrowseEvents (type.Events);
152
153                                 if (type.HasNestedTypes)
154                                         BrowseTypes (type.NestedTypes);
155                         }
156                 }
157
158                 void BrowseFields (ICollection fields)
159                 {
160                         foreach (FieldDefinition field in fields)
161                                 DispatchField (field);
162                 }
163
164                 void BrowseMethods (ICollection methods)
165                 {
166                         foreach (MethodDefinition method in methods)
167                                 DispatchMethod (method);
168                 }
169
170                 void BrowseProperties (ICollection properties)
171                 {
172                         foreach (PropertyDefinition property in properties)
173                                 DispatchProperty (property);
174                 }
175
176                 void BrowseEvents (ICollection events)
177                 {
178                         foreach (EventDefinition @event in events)
179                                 DispatchEvent (@event);
180                 }
181
182                 void DispatchAssembly (AssemblyDefinition assembly)
183                 {
184                         foreach (var substep in on_assemblies)
185                                 substep.ProcessAssembly (assembly);
186                 }
187
188                 void DispatchType (TypeDefinition type)
189                 {
190                         foreach (var substep in on_types)
191                                 substep.ProcessType (type);
192                 }
193
194                 void DispatchField (FieldDefinition field)
195                 {
196                         foreach (var substep in on_fields)
197                                 substep.ProcessField (field);
198                 }
199
200                 void DispatchMethod (MethodDefinition method)
201                 {
202                         foreach (var substep in on_methods)
203                                 substep.ProcessMethod (method);
204                 }
205
206                 void DispatchProperty (PropertyDefinition property)
207                 {
208                         foreach (var substep in on_properties)
209                                 substep.ProcessProperty (property);
210                 }
211
212                 void DispatchEvent (EventDefinition @event)
213                 {
214                         foreach (var substep in on_events)
215                                 substep.ProcessEvent (@event);
216                 }
217
218                 void InitializeSubSteps (LinkContext context)
219                 {
220                         foreach (var substep in substeps)
221                                 substep.Initialize (context);
222                 }
223
224                 void CategorizeSubSteps (AssemblyDefinition assembly)
225                 {
226                         on_assemblies = null;
227                         on_types = null;
228                         on_fields = null;
229                         on_methods = null;
230                         on_properties = null;
231                         on_events = null;
232
233                         foreach (var substep in substeps)
234                                 CategorizeSubStep (substep, assembly);
235                 }
236
237                 void CategorizeSubStep (ISubStep substep, AssemblyDefinition assembly)
238                 {
239                         if (!substep.IsActiveFor (assembly))
240                                 return;
241
242                         CategorizeTarget (substep, SubStepTargets.Assembly, ref on_assemblies);
243                         CategorizeTarget (substep, SubStepTargets.Type, ref on_types);
244                         CategorizeTarget (substep, SubStepTargets.Field, ref on_fields);
245                         CategorizeTarget (substep, SubStepTargets.Method, ref on_methods);
246                         CategorizeTarget (substep, SubStepTargets.Property, ref on_properties);
247                         CategorizeTarget (substep, SubStepTargets.Event, ref on_events);
248                 }
249
250                 static void CategorizeTarget (ISubStep substep, SubStepTargets target, ref List<ISubStep> list)
251                 {
252                         if (!Targets (substep, target))
253                                 return;
254
255                         if (list == null)
256                                 list = new List<ISubStep> ();
257
258                         list.Add (substep);
259                 }
260
261                 static bool Targets (ISubStep substep, SubStepTargets target)
262                 {
263                         return (substep.Targets & target) == target;
264                 }
265
266                 IEnumerator IEnumerable.GetEnumerator ()
267                 {
268                         return GetEnumerator ();
269                 }
270
271                 public IEnumerator<ISubStep> GetEnumerator ()
272                 {
273                         return substeps.GetEnumerator ();
274                 }
275         }
276 }