2007-08-01 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / tools / tuner / Mono.Tuner / CheckVisibility.cs
1 //
2 // CheckVisibility.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //
7 // (C) 2007 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
32 using Mono.Linker;
33 using Mono.Linker.Steps;
34
35 using Mono.Cecil;
36 using Mono.Cecil.Cil;
37
38 namespace Mono.Tuner {
39
40         public class CheckVisibility : BaseStep {
41
42                 protected override void ProcessAssembly (AssemblyDefinition assembly)
43                 {
44                         if (assembly.Name.Name == "smcs")
45                                 return;
46
47                         foreach (ModuleDefinition module in assembly.Modules)
48                                 foreach (TypeDefinition type in module.Types)
49                                         CheckType (type);
50                 }
51
52                 void CheckType (TypeDefinition type)
53                 {
54                         if (!IsVisibleFrom (type, type.BaseType)) {
55                                 Report ("Base type {0} of type {1} is not visible",
56                                         type.BaseType, type);
57                         }
58                         
59                         CheckInterfaces (type);
60                         
61                         CheckFields (type);
62                         CheckConstructors (type);
63                         CheckMethods (type);
64                 }
65
66                 void CheckInterfaces (TypeDefinition type)
67                 {
68                         foreach (TypeReference iface in type.Interfaces) {
69                                 if (!IsVisibleFrom (type, iface)) {
70                                         Report ("Interface {0} implemented by {1} is not visible",
71                                                 iface, type);
72                                 }
73                         }
74                 }
75
76                 static bool IsPublic (TypeDefinition type)
77                 {
78                         return (type.Attributes & TypeAttributes.Public) != 0;
79                 }
80
81                 static bool AreInDifferentAssemblies (TypeDefinition lhs, TypeDefinition rhs)
82                 {
83                         return lhs.Module.Assembly.Name.FullName != rhs.Module.Assembly.Name.FullName;
84                 }
85
86                 bool IsVisibleFrom (TypeDefinition type, TypeReference reference)
87                 {                       
88 //                      Report ("[is-visible-from] {0}:{1}", type, reference);
89                         
90                         if (reference == null)
91                                 return true;
92
93                         if (reference is GenericParameter || reference.GetOriginalType () is GenericParameter)
94                                 return true;
95         
96                         TypeDefinition other = Context.Resolver.Resolve (reference);
97                         if (other == null)
98                                 return true;
99
100                         if (!AreInDifferentAssemblies (type, other))
101                                 return true;
102                         
103                         if (IsPublic (other))
104                                 return true;
105                         
106                         return false;
107                 }
108
109                 void Report (string pattern, params object [] parameters)
110                 {
111                         Console.WriteLine ("[check] " + pattern, parameters);
112                 }
113
114                 void CheckFields (TypeDefinition type)
115                 {
116                         foreach (FieldDefinition field in type.Fields) {
117                                 if (!IsVisibleFrom (type, field.FieldType)) {
118                                         Report ("Field {0} of type {1} is not visible from {2}",
119                                                 field.Name, field.FieldType, type);
120                                 }
121                         }
122                 }
123
124                 void CheckConstructors (TypeDefinition type)
125                 {
126                         CheckMethods (type, type.Constructors);
127                 }
128
129                 void CheckMethods (TypeDefinition type)
130                 {
131                         CheckMethods (type, type.Methods);
132                 }
133
134                 void CheckMethods (TypeDefinition type, ICollection methods)
135                 {
136                         foreach (MethodDefinition method in methods) {
137                                 if (!IsVisibleFrom (type, method.ReturnType.ReturnType)) {
138                                         Report ("Method return type {0} in method {1} is not visible",
139                                                 method.ReturnType.ReturnType, method);
140                                 }
141                                 
142                                 foreach (ParameterDefinition parameter in method.Parameters) {
143                                         if (!IsVisibleFrom (type, parameter.ParameterType)) {
144                                                 Report ("Parameter {0} of type {1} in method {2} is not visible.",
145                                                         parameter.Sequence, parameter.ParameterType, method);
146                                         }
147                                 }
148
149                                 if (method.HasBody)
150                                         CheckBody (method);
151                         }
152                 }
153
154                 void CheckBody (MethodDefinition method)
155                 {
156                         foreach (VariableDefinition variable in method.Body.Variables) {
157                                 if (!IsVisibleFrom ((TypeDefinition) method.DeclaringType, variable.VariableType)) {
158                                         Report ("Variable {0} of type {1} from method {2} is not visible",
159                                                 variable.Index, variable.VariableType, method);
160                                 }
161                         }
162                         
163                         foreach (Instruction instr in method.Body.Instructions) {
164                                 switch (instr.OpCode.OperandType) {
165                                 case OperandType.InlineType:
166                                 case OperandType.InlineMethod:
167                                 case OperandType.InlineField:
168                                 case OperandType.InlineTok:
169                                 default:
170                                         continue;
171                                 }
172                         }
173                 }
174         }
175 }