Remove IVT from System.ServiceModel on MonoDroid, MonoTouch profiles.
[mono.git] / mcs / tools / tuner / Mono.Tuner / MoonlightA11yProcessor.cs
1 //
2 // MoonlightA11yProcessor.cs
3 //
4 // Author:
5 //   AndrĂ©s G. Aragoneses (aaragoneses@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
30 using System;
31
32 using Mono.Cecil;
33
34 using Mono.Linker;
35
36 namespace Mono.Tuner {
37         
38         public class MoonlightA11yProcessor : InjectSecurityAttributes {
39                 
40                 protected override bool ConditionToProcess ()
41                 {
42                         return true;
43                 }
44                 
45                 protected override void ProcessAssembly (AssemblyDefinition assembly)
46                 {
47                         if (Annotations.GetAction (assembly) != AssemblyAction.Link)
48                                 return;
49
50                         _assembly = assembly;
51
52                         // remove existing [SecurityCritical] and [SecuritySafeCritical]
53                         RemoveSecurityAttributes ();
54
55                         // add [SecurityCritical]
56                         AddSecurityAttributes ();
57                         
58                         // convert all public members into internal
59                         MakeApiInternal ();
60                 }
61                 
62                 void MakeApiInternal ()
63                 {
64                         foreach (TypeDefinition type in _assembly.MainModule.Types) {
65                                 if (type.IsPublic)
66                                         type.IsPublic = false;
67
68                                 if (type.HasConstructors && !type.Name.EndsWith ("Adapter"))
69                                         foreach (MethodDefinition ctor in type.Constructors)
70                                                 if (ctor.IsPublic)
71                                                         ctor.IsAssembly = true;
72
73                                 if (type.HasMethods)
74                                         foreach (MethodDefinition method in type.Methods)
75                                                 if (method.IsPublic)
76                                                         method.IsAssembly = true;
77                         }
78                 }
79                 
80                 void AddSecurityAttributes ()
81                 {
82                         foreach (TypeDefinition type in _assembly.MainModule.Types) {
83                                 AddCriticalAttribute (type);
84
85                                 if (type.HasConstructors)
86                                         foreach (MethodDefinition ctor in type.Constructors)
87                                                 AddCriticalAttribute (ctor);
88
89                                 if (type.HasMethods)
90                                         foreach (MethodDefinition method in type.Methods) {
91                                                 MethodDefinition parent = null;
92                                         
93                                                 //TODO: take in account generic params
94                                                 if (!method.HasGenericParameters) {
95                                                         
96                                                         /*
97                                                          * we need to scan base methods because the CoreCLR complains about SC attribs added
98                                                          * to overriden methods whose base (virtual or interface) method is not marked as SC
99                                                          * with TypeLoadExceptions
100                                                          */
101                                                         parent = GetBaseMethod (type, method);
102                                                 }
103
104                                                 //if there's no base method
105                                                 if (parent == null ||
106
107                                                 //if it's our bridge assembly, we're sure it will (finally, at the end of the linking process) have the SC attrib
108                                                     _assembly.MainModule.Types.Contains (parent.DeclaringType) ||
109
110                                                 //if the type is in the moonlight assemblies, check if it has the SC attrib
111                                                     HasSecurityAttribute (parent, AttributeType.Critical))
112
113                                                         AddCriticalAttribute (method);
114                                 }
115                                 
116                         }
117                 }
118                 
119                 MethodDefinition GetBaseMethod (TypeDefinition finalType, MethodDefinition final)
120                 {
121                         // both GetOverridenMethod and GetInterfaceMethod return null if there is no base method
122                         return GetOverridenMethod (finalType, final) ?? GetInterfaceMethod (finalType, final);
123                 }
124                 
125                 //note: will not return abstract methods
126                 MethodDefinition GetOverridenMethod (TypeDefinition finalType, MethodDefinition final)
127                 {
128                         TypeReference baseType = finalType.BaseType;
129                         while (baseType != null && baseType.Resolve () != null) {
130                                 foreach (MethodDefinition method in baseType.Resolve ().Methods) {
131                                         if (!method.IsVirtual || method.Name != final.Name)
132                                                 continue;
133                                         
134                                         //TODO: should we discard them?
135                                         if (method.IsAbstract)
136                                                 continue;
137                                         
138                                         if (HasSameSignature (method, final))
139                                                 return method;
140                                 }
141                                 baseType = baseType.Resolve().BaseType;
142                         }
143                         return null;
144                 }
145                 
146                 MethodDefinition GetInterfaceMethod (TypeDefinition finalType, MethodDefinition final)
147                 {
148                         TypeDefinition baseType = finalType;
149                         while (baseType != null) {
150                                 if (baseType.HasInterfaces)
151                                         foreach (TypeReference @interface in baseType.Interfaces)
152                                                 foreach (MethodDefinition method in @interface.Resolve ().Methods)
153                                                         if (method.Name == final.Name && HasSameSignature (method, final))
154                                                                 return method;
155
156                                 baseType = baseType.BaseType == null ? null : baseType.BaseType.Resolve ();
157                         }
158                         return null;
159                 }
160                 
161                 bool HasSameSignature (MethodDefinition method1, MethodDefinition method2)
162                 {
163                         if (method1.ReturnType.ReturnType.FullName != method2.ReturnType.ReturnType.FullName)
164                                 return false;
165                         
166                         if (method1.Parameters.Count != method2.Parameters.Count)
167                                 return false;
168
169                         for (int i = 0; i < method1.Parameters.Count; i++) {
170                                 if (method1.Parameters [i].ParameterType.FullName !=
171                                     method2.Parameters [i].ParameterType.FullName)
172                                         return false;
173                         }
174                         
175                         return true;
176                 }
177         }
178 }