9dcf5ee05afc4e9bc4a51658a00738dff404443d
[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                                 var bs = substep as BaseSubStep;
186                                 if (bs != null)
187                                         bs.Annotations.Push (substep);
188                                 substep.ProcessAssembly (assembly);
189                                 if (bs != null)
190                                         bs.Annotations.Pop ();
191                         }
192                 }
193
194                 void DispatchType (TypeDefinition type)
195                 {
196                         foreach (var substep in on_types) {
197                                 var bs = substep as BaseSubStep;
198                                 if (bs != null)
199                                         bs.Annotations.Push (substep);
200                                 substep.ProcessType (type);
201                                 if (bs != null)
202                                         bs.Annotations.Pop ();
203                         }
204                 }
205
206                 void DispatchField (FieldDefinition field)
207                 {
208                         foreach (var substep in on_fields)
209                                 substep.ProcessField (field);
210                 }
211
212                 void DispatchMethod (MethodDefinition method)
213                 {
214                         foreach (var substep in on_methods)
215                                 substep.ProcessMethod (method);
216                 }
217
218                 void DispatchProperty (PropertyDefinition property)
219                 {
220                         foreach (var substep in on_properties)
221                                 substep.ProcessProperty (property);
222                 }
223
224                 void DispatchEvent (EventDefinition @event)
225                 {
226                         foreach (var substep in on_events)
227                                 substep.ProcessEvent (@event);
228                 }
229
230                 void InitializeSubSteps (LinkContext context)
231                 {
232                         foreach (var substep in substeps)
233                                 substep.Initialize (context);
234                 }
235
236                 void CategorizeSubSteps (AssemblyDefinition assembly)
237                 {
238                         on_assemblies = null;
239                         on_types = null;
240                         on_fields = null;
241                         on_methods = null;
242                         on_properties = null;
243                         on_events = null;
244
245                         foreach (var substep in substeps)
246                                 CategorizeSubStep (substep, assembly);
247                 }
248
249                 void CategorizeSubStep (ISubStep substep, AssemblyDefinition assembly)
250                 {
251                         if (!substep.IsActiveFor (assembly))
252                                 return;
253
254                         CategorizeTarget (substep, SubStepTargets.Assembly, ref on_assemblies);
255                         CategorizeTarget (substep, SubStepTargets.Type, ref on_types);
256                         CategorizeTarget (substep, SubStepTargets.Field, ref on_fields);
257                         CategorizeTarget (substep, SubStepTargets.Method, ref on_methods);
258                         CategorizeTarget (substep, SubStepTargets.Property, ref on_properties);
259                         CategorizeTarget (substep, SubStepTargets.Event, ref on_events);
260                 }
261
262                 static void CategorizeTarget (ISubStep substep, SubStepTargets target, ref List<ISubStep> list)
263                 {
264                         if (!Targets (substep, target))
265                                 return;
266
267                         if (list == null)
268                                 list = new List<ISubStep> ();
269
270                         list.Add (substep);
271                 }
272
273                 static bool Targets (ISubStep substep, SubStepTargets target)
274                 {
275                         return (substep.Targets & target) == target;
276                 }
277
278                 IEnumerator IEnumerable.GetEnumerator ()
279                 {
280                         return GetEnumerator ();
281                 }
282
283                 public IEnumerator<ISubStep> GetEnumerator ()
284                 {
285                         return substeps.GetEnumerator ();
286                 }
287         }
288 }