update tuner
[mono.git] / mcs / tools / tuner / MonoMac.Tuner / MarkNSObjects.cs
1 //
2 // MarkNSObbjects.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //
7 // (C) 2009 Novell, Inc.
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using System.Linq;
33
34 using Mono.Linker;
35 using Mono.Linker.Steps;
36
37 using Mono.Tuner;
38
39 using Mono.Cecil;
40
41 namespace MonoMac.Tuner {
42
43         public class MarkNSObjects : BaseSubStep {
44
45                 const string ExportAttribute = "MonoMac.Foundation.ExportAttribute";
46                 const string MonoMacAssembly = "MonoMac";
47
48                 public override SubStepTargets Targets {
49                         get { return SubStepTargets.Type; }
50                 }
51
52                 public override void ProcessType (TypeDefinition type)
53                 {
54                         if (!type.IsNSObject () || !type.IsNativeObject ())
55                                 return;
56
57                         if (!IsMonoMacType (type)) {
58                                 Annotations.Mark (type);
59                                 Annotations.SetPreserve (type, TypePreserve.All);
60                         } else
61                                 PreserveMonoMacType (type);
62                 }
63
64                 void PreserveMonoMacType (TypeDefinition type)
65                 {
66                         PreserveIntPtrConstructor (type);
67                         PreserveExportedMethods (type);
68                 }
69
70                 void PreserveExportedMethods (TypeDefinition type)
71                 {
72                         if (!type.HasMethods)
73                                 return;
74
75                         foreach (var method in type.GetMethods ()) {
76                                 if (!IsExportedMethod (method))
77                                         continue;
78
79                                 if (!IsOverridenInUserCode (method))
80                                         continue;
81
82                                 PreserveMethod (type, method);
83                         }
84                 }
85
86                 bool IsOverridenInUserCode (MethodDefinition method)
87                 {
88                         if (!method.IsVirtual)
89                                 return false;
90
91                         var overrides = Annotations.GetOverrides (method);
92                         if (overrides == null || overrides.Count == 0)
93                                 return false;
94
95                         foreach (MethodDefinition @override in overrides)
96                                 if (!IsMonoMacMethod (@override))
97                                         return true;
98
99                         return false;
100                 }
101
102                 static bool IsExportedMethod (MethodDefinition method)
103                 {
104                         return HasExportAttribute (method);
105                 }
106
107                 static bool HasExportAttribute (ICustomAttributeProvider provider)
108                 {
109                         if (!provider.HasCustomAttributes)
110                                 return false;
111
112                         foreach (CustomAttribute attribute in provider.CustomAttributes)
113                                 if (attribute.AttributeType.FullName == ExportAttribute)
114                                         return true;
115
116                         return false;
117                 }
118
119                 void PreserveIntPtrConstructor (TypeDefinition type)
120                 {
121                         if (!type.HasMethods)
122                                 return;
123
124                         foreach (MethodDefinition constructor in type.GetConstructors ()) {
125                                 if (!constructor.HasParameters)
126                                         continue;
127
128                                 if (constructor.Parameters.Count != 1 || constructor.Parameters [0].ParameterType.FullName != "System.IntPtr")
129                                         continue;
130
131                                 PreserveMethod (type, constructor);
132                         }
133                 }
134
135                 void PreserveMethod (TypeDefinition type, MethodDefinition method)
136                 {
137                         Annotations.AddPreservedMethod (type, method);
138                 }
139
140                 static bool IsMonoMacMethod (MethodDefinition method)
141                 {
142                         return IsMonoMacType (method.DeclaringType);
143                 }
144
145                 static bool IsMonoMacType (TypeDefinition type)
146                 {
147                         return type.Module.Assembly.Name.Name == MonoMacAssembly;
148                 }
149         }
150 }