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 foreach (var attribute in GetPreserveAttributes (field))
41 Mark (field, attribute);
44 public override void ProcessMethod (MethodDefinition method)
46 MarkMethodIfPreserved (method);
49 public override void ProcessProperty (PropertyDefinition property)
51 foreach (var attribute in GetPreserveAttributes (property)) {
52 MarkMethod (property.GetMethod, attribute);
53 MarkMethod (property.SetMethod, attribute);
57 public override void ProcessEvent (EventDefinition @event)
59 foreach (var attribute in GetPreserveAttributes (@event)) {
60 MarkMethod (@event.AddMethod, attribute);
61 MarkMethod (@event.InvokeMethod, attribute);
62 MarkMethod (@event.RemoveMethod, attribute);
66 void MarkMethodIfPreserved (MethodDefinition method)
68 foreach (var attribute in GetPreserveAttributes (method))
69 MarkMethod (method, attribute);
72 void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute)
77 Mark (method, preserve_attribute);
78 Annotations.SetAction (method, MethodAction.Parse);
81 void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute)
83 if (IsConditionalAttribute (preserve_attribute)) {
84 PreserveConditional (provider);
88 PreserveUnconditional (provider);
91 void PreserveConditional (IMetadataTokenProvider provider)
93 var method = provider as MethodDefinition;
95 // workaround to support (uncommon but valid) conditional fields form [Preserve]
96 PreserveUnconditional (provider);
100 Annotations.AddPreservedMethod (method.DeclaringType, method);
103 static bool IsConditionalAttribute (CustomAttribute attribute)
105 if (attribute == null)
108 foreach (var named_argument in attribute.Fields)
109 if (named_argument.Name == "Conditional")
110 return (bool) named_argument.Argument.Value;
115 void PreserveUnconditional (IMetadataTokenProvider provider)
117 Annotations.Mark (provider);
119 var member = provider as IMemberDefinition;
120 if (member == null || member.DeclaringType == null)
123 Mark (member.DeclaringType, null);
126 void TryApplyPreserveAttribute (TypeDefinition type)
128 foreach (var attribute in GetPreserveAttributes (type)) {
129 Annotations.Mark (type);
131 if (!attribute.HasFields)
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);
140 List<CustomAttribute> GetPreserveAttributes (ICustomAttributeProvider provider)
142 List<CustomAttribute> attrs = new List<CustomAttribute> ();
144 if (!provider.HasCustomAttributes)
147 var attributes = provider.CustomAttributes;
149 for (int i = attributes.Count - 1; i >= 0; i--) {
150 var attribute = attributes [i];
152 bool remote_attribute;
153 if (!IsPreservedAttribute (provider, attribute, out remote_attribute))
156 attrs.Add (attribute);
157 if (remote_attribute)
158 attributes.RemoveAt (i);