[w32handle] Stop returning 0 in every cases for locking/unlocking (#3926)
[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                         foreach (var attribute in GetPreserveAttributes (field))
41                                 Mark (field, attribute);
42                 }
43
44                 public override void ProcessMethod (MethodDefinition method)
45                 {
46                         MarkMethodIfPreserved (method);
47                 }
48
49                 public override void ProcessProperty (PropertyDefinition property)
50                 {
51                         foreach (var attribute in GetPreserveAttributes (property)) {
52                                 MarkMethod (property.GetMethod, attribute);
53                                 MarkMethod (property.SetMethod, attribute);
54                         }
55                 }
56
57                 public override void ProcessEvent (EventDefinition @event)
58                 {
59                         foreach (var attribute in GetPreserveAttributes (@event)) {
60                                 MarkMethod (@event.AddMethod, attribute);
61                                 MarkMethod (@event.InvokeMethod, attribute);
62                                 MarkMethod (@event.RemoveMethod, attribute);
63                         }
64                 }
65
66                 void MarkMethodIfPreserved (MethodDefinition method)
67                 {
68                         foreach (var attribute in GetPreserveAttributes (method)) 
69                                 MarkMethod (method, attribute);
70                 }
71
72                 void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute)
73                 {
74                         if (method == null)
75                                 return;
76
77                         Mark (method, preserve_attribute);
78                         Annotations.SetAction (method, MethodAction.Parse);
79                 }
80
81                 void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute)
82                 {
83                         if (IsConditionalAttribute (preserve_attribute)) {
84                                 PreserveConditional (provider);
85                                 return;
86                         }
87
88                         PreserveUnconditional (provider);
89                 }
90
91                 void PreserveConditional (IMetadataTokenProvider provider)
92                 {
93                         var method = provider as MethodDefinition;
94                         if (method == null) {
95                                 // workaround to support (uncommon but valid) conditional fields form [Preserve]
96                                 PreserveUnconditional (provider);
97                                 return;
98                         }
99
100                         Annotations.AddPreservedMethod (method.DeclaringType, method);
101                 }
102
103                 static bool IsConditionalAttribute (CustomAttribute attribute)
104                 {
105                         if (attribute == null)
106                                 return false;
107
108                         foreach (var named_argument in attribute.Fields)
109                                 if (named_argument.Name == "Conditional")
110                                         return (bool) named_argument.Argument.Value;
111
112                         return false;
113                 }
114
115                 void PreserveUnconditional (IMetadataTokenProvider provider)
116                 {
117                         Annotations.Mark (provider);
118
119                         var member = provider as IMemberDefinition;
120                         if (member == null || member.DeclaringType == null)
121                                 return;
122
123                         Mark (member.DeclaringType, null);
124                 }
125
126                 void TryApplyPreserveAttribute (TypeDefinition type)
127                 {
128                         foreach (var attribute in GetPreserveAttributes (type)) {
129                                 Annotations.Mark (type);
130
131                                 if (!attribute.HasFields)
132                                         continue;
133  
134                                 foreach (var named_argument in attribute.Fields)
135                                         if (named_argument.Name == "AllMembers" && (bool)named_argument.Argument.Value)
136                                                 Annotations.SetPreserve (type, TypePreserve.All);
137                         }
138                 }
139
140                 List<CustomAttribute> GetPreserveAttributes (ICustomAttributeProvider provider)
141                 {
142                         List<CustomAttribute> attrs = new List<CustomAttribute> ();
143
144                         if (!provider.HasCustomAttributes)
145                                 return attrs;
146
147                         var attributes = provider.CustomAttributes;
148
149                         for (int i = attributes.Count - 1; i >= 0; i--) {
150                                 var attribute = attributes [i];
151
152                                 bool remote_attribute;
153                                 if (!IsPreservedAttribute (provider, attribute, out remote_attribute))
154                                         continue;
155
156                                 attrs.Add (attribute);
157                                 if (remote_attribute)
158                                         attributes.RemoveAt (i);
159                         }
160
161                         return attrs;
162                 }
163         }
164 }