2 using System.Collections;
3 using System.Collections.Generic;
7 using Mono.Linker.Steps;
11 namespace Mono.Tuner {
13 public abstract class ApplyPreserveAttributeBase : BaseSubStep {
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);
18 public override SubStepTargets Targets {
20 return SubStepTargets.Type
21 | SubStepTargets.Field
22 | SubStepTargets.Method
23 | SubStepTargets.Property
24 | SubStepTargets.Event;
28 public override bool IsActiveFor (AssemblyDefinition assembly)
30 return !Profile.IsSdkAssembly (assembly) && Annotations.GetAction (assembly) == AssemblyAction.Link;
33 public override void ProcessType (TypeDefinition type)
35 TryApplyPreserveAttribute (type);
38 public override void ProcessField (FieldDefinition field)
40 var attribute = GetPreserveAttribute (field);
41 if (attribute == null)
44 Mark (field, attribute);
47 public override void ProcessMethod (MethodDefinition method)
49 MarkMethodIfPreserved (method);
52 public override void ProcessProperty (PropertyDefinition property)
54 var attribute = GetPreserveAttribute (property);
55 if (attribute == null)
58 MarkMethod (property.GetMethod, attribute);
59 MarkMethod (property.SetMethod, attribute);
62 public override void ProcessEvent (EventDefinition @event)
64 var attribute = GetPreserveAttribute (@event);
65 if (attribute == null)
68 MarkMethod (@event.AddMethod, attribute);
69 MarkMethod (@event.InvokeMethod, attribute);
70 MarkMethod (@event.RemoveMethod, attribute);
73 void MarkMethodIfPreserved (MethodDefinition method)
75 var attribute = GetPreserveAttribute (method);
76 if (attribute == null)
79 MarkMethod (method, attribute);
82 void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute)
87 Mark (method, preserve_attribute);
88 Annotations.SetAction (method, MethodAction.Parse);
91 void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute)
93 if (IsConditionalAttribute (preserve_attribute)) {
94 PreserveConditional (provider);
98 PreserveUnconditional (provider);
101 void PreserveConditional (IMetadataTokenProvider provider)
103 var method = provider as MethodDefinition;
104 if (method == null) {
105 // workaround to support (uncommon but valid) conditional fields form [Preserve]
106 PreserveUnconditional (provider);
110 Annotations.AddPreservedMethod (method.DeclaringType, method);
113 static bool IsConditionalAttribute (CustomAttribute attribute)
115 if (attribute == null)
118 foreach (var named_argument in attribute.Fields)
119 if (named_argument.Name == "Conditional")
120 return (bool) named_argument.Argument.Value;
125 void PreserveUnconditional (IMetadataTokenProvider provider)
127 Annotations.Mark (provider);
129 var member = provider as IMemberDefinition;
130 if (member == null || member.DeclaringType == null)
133 Mark (member.DeclaringType, null);
136 void TryApplyPreserveAttribute (TypeDefinition type)
138 var attribute = GetPreserveAttribute (type);
139 if (attribute == null)
142 Annotations.Mark (type);
144 if (!attribute.HasFields)
147 foreach (var named_argument in attribute.Fields)
148 if (named_argument.Name == "AllMembers" && (bool) named_argument.Argument.Value)
149 Annotations.SetPreserve (type, TypePreserve.All);
152 CustomAttribute GetPreserveAttribute (ICustomAttributeProvider provider)
154 if (!provider.HasCustomAttributes)
157 var attributes = provider.CustomAttributes;
159 for (int i = 0; i < attributes.Count; i++) {
160 var attribute = attributes [i];
162 bool remote_attribute;
163 if (!IsPreservedAttribute (provider, attribute, out remote_attribute))
166 if (remote_attribute)
167 attributes.RemoveAt (i);