Merge pull request #121 from LogosBible/processfixes
[mono.git] / mcs / tools / tuner / Mono.Tuner / ApplyPreserveAttributeBase.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Linq;
5
6 using Mono.Linker;
7 using Mono.Linker.Steps;
8
9 using Mono.Cecil;
10
11 namespace Mono.Tuner {
12
13         public abstract class ApplyPreserveAttributeBase : BaseSubStep {
14
15                 protected abstract string PreserveAttribute { get; }
16
17                 public override SubStepTargets Targets {
18                         get {
19                                 return SubStepTargets.Type
20                                         | SubStepTargets.Field
21                                         | SubStepTargets.Method
22                                         | SubStepTargets.Property
23                                         | SubStepTargets.Event;
24                         }
25                 }
26
27                 public override bool IsActiveFor (AssemblyDefinition assembly)
28                 {
29                         return !Profile.IsSdkAssembly (assembly) && Annotations.GetAction (assembly) == AssemblyAction.Link;
30                 }
31
32                 public override void ProcessType (TypeDefinition type)
33                 {
34                         TryApplyPreserveAttribute (type);
35                 }
36
37                 public override void ProcessField (FieldDefinition field)
38                 {
39                         var attribute = GetPreserveAttribute (field);
40                         if (attribute == null)
41                                 return;
42
43                         Mark (field, attribute);
44                 }
45
46                 public override void ProcessMethod (MethodDefinition method)
47                 {
48                         MarkMethodIfPreserved (method);
49                 }
50
51                 public override void ProcessProperty (PropertyDefinition property)
52                 {
53                         var attribute = GetPreserveAttribute (property);
54                         if (attribute == null)
55                                 return;
56
57                         MarkMethod (property.GetMethod, attribute);
58                         MarkMethod (property.SetMethod, attribute);
59                 }
60
61                 public override void ProcessEvent (EventDefinition @event)
62                 {
63                         var attribute = GetPreserveAttribute (@event);
64                         if (attribute == null)
65                                 return;
66
67                         MarkMethod (@event.AddMethod, attribute);
68                         MarkMethod (@event.InvokeMethod, attribute);
69                         MarkMethod (@event.RemoveMethod, attribute);
70                 }
71
72                 void MarkMethodIfPreserved (MethodDefinition method)
73                 {
74                         var attribute = GetPreserveAttribute (method);
75                         if (attribute == null)
76                                 return;
77
78                         MarkMethod (method, attribute);
79                 }
80
81                 void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute)
82                 {
83                         if (method == null)
84                                 return;
85
86                         Mark (method, preserve_attribute);
87                         Annotations.SetAction (method, MethodAction.Parse);
88                 }
89
90                 void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute)
91                 {
92                         if (IsConditionalAttribute (preserve_attribute)) {
93                                 PreserveConditional (provider);
94                                 return;
95                         }
96
97                         PreserveUnconditional (provider);
98                 }
99
100                 void PreserveConditional (IMetadataTokenProvider provider)
101                 {
102                         var method = provider as MethodDefinition;
103                         if (method == null)
104                                 return;
105
106                         Annotations.AddPreservedMethod (method.DeclaringType, method);
107                 }
108
109                 static bool IsConditionalAttribute (CustomAttribute attribute)
110                 {
111                         if (attribute == null)
112                                 return false;
113
114                         foreach (var named_argument in attribute.Fields)
115                                 if (named_argument.Name == "Conditional")
116                                         return (bool) named_argument.Argument.Value;
117
118                         return false;
119                 }
120
121                 void PreserveUnconditional (IMetadataTokenProvider provider)
122                 {
123                         Annotations.Mark (provider);
124
125                         var member = provider as IMemberDefinition;
126                         if (member == null || member.DeclaringType == null)
127                                 return;
128
129                         Mark (member.DeclaringType, null);
130                 }
131
132                 void TryApplyPreserveAttribute (TypeDefinition type)
133                 {
134                         var attribute = GetPreserveAttribute (type);
135                         if (attribute == null)
136                                 return;
137
138                         Annotations.Mark (type);
139
140                         foreach (var named_argument in attribute.Fields)
141                                 if (named_argument.Name == "AllMembers" && (bool) named_argument.Argument.Value)
142                                         Annotations.SetPreserve (type, TypePreserve.All);
143                 }
144
145                 CustomAttribute GetPreserveAttribute (ICustomAttributeProvider provider)
146                 {
147                         if (!provider.HasCustomAttributes)
148                                 return null;
149
150                         var attributes = provider.CustomAttributes;
151
152                         for (int i = 0; i < attributes.Count; i++) {
153                                 var attribute = attributes [i];
154
155                                 if (attribute.Constructor.DeclaringType.FullName != PreserveAttribute)
156                                         continue;
157
158                                 attributes.RemoveAt (i);
159                                 return attribute;
160                         }
161
162                         return null;
163                 }
164         }
165 }