Merge pull request #273 from joncham/bug-getpid
[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                 // set 'removeAttribute' to true if you want the preserved attribute to be removed from the final assembly
16                 protected abstract bool IsPreservedAttribute (ICustomAttributeProvider provider, CustomAttribute attribute, out bool removeAttribute);
17
18                 public override SubStepTargets Targets {
19                         get {
20                                 return SubStepTargets.Type
21                                         | SubStepTargets.Field
22                                         | SubStepTargets.Method
23                                         | SubStepTargets.Property
24                                         | SubStepTargets.Event;
25                         }
26                 }
27
28                 public override bool IsActiveFor (AssemblyDefinition assembly)
29                 {
30                         return !Profile.IsSdkAssembly (assembly) && Annotations.GetAction (assembly) == AssemblyAction.Link;
31                 }
32
33                 public override void ProcessType (TypeDefinition type)
34                 {
35                         TryApplyPreserveAttribute (type);
36                 }
37
38                 public override void ProcessField (FieldDefinition field)
39                 {
40                         var attribute = GetPreserveAttribute (field);
41                         if (attribute == null)
42                                 return;
43
44                         Mark (field, attribute);
45                 }
46
47                 public override void ProcessMethod (MethodDefinition method)
48                 {
49                         MarkMethodIfPreserved (method);
50                 }
51
52                 public override void ProcessProperty (PropertyDefinition property)
53                 {
54                         var attribute = GetPreserveAttribute (property);
55                         if (attribute == null)
56                                 return;
57
58                         MarkMethod (property.GetMethod, attribute);
59                         MarkMethod (property.SetMethod, attribute);
60                 }
61
62                 public override void ProcessEvent (EventDefinition @event)
63                 {
64                         var attribute = GetPreserveAttribute (@event);
65                         if (attribute == null)
66                                 return;
67
68                         MarkMethod (@event.AddMethod, attribute);
69                         MarkMethod (@event.InvokeMethod, attribute);
70                         MarkMethod (@event.RemoveMethod, attribute);
71                 }
72
73                 void MarkMethodIfPreserved (MethodDefinition method)
74                 {
75                         var attribute = GetPreserveAttribute (method);
76                         if (attribute == null)
77                                 return;
78
79                         MarkMethod (method, attribute);
80                 }
81
82                 void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute)
83                 {
84                         if (method == null)
85                                 return;
86
87                         Mark (method, preserve_attribute);
88                         Annotations.SetAction (method, MethodAction.Parse);
89                 }
90
91                 void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute)
92                 {
93                         if (IsConditionalAttribute (preserve_attribute)) {
94                                 PreserveConditional (provider);
95                                 return;
96                         }
97
98                         PreserveUnconditional (provider);
99                 }
100
101                 void PreserveConditional (IMetadataTokenProvider provider)
102                 {
103                         var method = provider as MethodDefinition;
104                         if (method == null) {
105                                 // workaround to support (uncommon but valid) conditional fields form [Preserve]
106                                 PreserveUnconditional (provider);
107                                 return;
108                         }
109
110                         Annotations.AddPreservedMethod (method.DeclaringType, method);
111                 }
112
113                 static bool IsConditionalAttribute (CustomAttribute attribute)
114                 {
115                         if (attribute == null)
116                                 return false;
117
118                         foreach (var named_argument in attribute.Fields)
119                                 if (named_argument.Name == "Conditional")
120                                         return (bool) named_argument.Argument.Value;
121
122                         return false;
123                 }
124
125                 void PreserveUnconditional (IMetadataTokenProvider provider)
126                 {
127                         Annotations.Mark (provider);
128
129                         var member = provider as IMemberDefinition;
130                         if (member == null || member.DeclaringType == null)
131                                 return;
132
133                         Mark (member.DeclaringType, null);
134                 }
135
136                 void TryApplyPreserveAttribute (TypeDefinition type)
137                 {
138                         var attribute = GetPreserveAttribute (type);
139                         if (attribute == null)
140                                 return;
141
142                         Annotations.Mark (type);
143
144                         foreach (var named_argument in attribute.Fields)
145                                 if (named_argument.Name == "AllMembers" && (bool) named_argument.Argument.Value)
146                                         Annotations.SetPreserve (type, TypePreserve.All);
147                 }
148
149                 CustomAttribute GetPreserveAttribute (ICustomAttributeProvider provider)
150                 {
151                         if (!provider.HasCustomAttributes)
152                                 return null;
153
154                         var attributes = provider.CustomAttributes;
155
156                         for (int i = 0; i < attributes.Count; i++) {
157                                 var attribute = attributes [i];
158
159                                 bool remote_attribute;
160                                 if (!IsPreservedAttribute (provider, attribute, out remote_attribute))
161                                         continue;
162
163                                 if (remote_attribute)
164                                         attributes.RemoveAt (i);
165                                 return attribute;
166                         }
167
168                         return null;
169                 }
170         }
171 }