1 // Mono.Util.CorCompare.MissingType
4 // Nick Drochak (ndrochak@gol.com)
6 // (C) 2001-2002 Nick Drochak
10 using System
.Reflection
;
11 using System
.Collections
;
13 namespace Mono
.Util
.CorCompare
17 /// Represents a class method that missing.
21 /// created on - 2/20/2002 10:43:57 PM
23 class MissingType
: MissingBase
25 // e.g. <class name="System.Byte" status="missing"/>
26 // e.g. <class name="System.Array" status="todo" missing="5" todo="6" complete="45">
27 Type typeMono
, typeMS
;
28 // ArrayList rgAttributes = new ArrayList ();
29 ArrayList rgMethods
= new ArrayList ();
30 ArrayList rgProperties
= new ArrayList ();
31 ArrayList rgEvents
= new ArrayList ();
32 ArrayList rgFields
= new ArrayList ();
33 ArrayList rgConstructors
= new ArrayList ();
34 ArrayList rgNestedTypes
= new ArrayList ();
35 ArrayList rgInterfaces
= new ArrayList ();
36 // NodeStatus nsAttributes = new NodeStatus ();
37 NodeStatus nsMethods
= new NodeStatus ();
38 NodeStatus nsProperties
= new NodeStatus ();
39 NodeStatus nsEvents
= new NodeStatus ();
40 NodeStatus nsFields
= new NodeStatus ();
41 NodeStatus nsConstructors
= new NodeStatus ();
42 NodeStatus nsNestedTypes
= new NodeStatus ();
43 NodeStatus nsInterfaces
= new NodeStatus ();
45 public MissingType (Type _typeMono
, Type _typeMS
)
49 m_nodeStatus
= new NodeStatus (_typeMono
, _typeMS
);
52 public override string Name
56 Type type
= TypeInfoBest
;
57 if (type
.DeclaringType
!= null)
58 return type
.DeclaringType
.Name
+ "+" + type
.Name
;
63 public override string Type
70 else if (type
.IsInterface
)
72 else if (type
.IsValueType
)
83 get { return (typeMono != null) ? typeMono : typeMS; }
86 public Type TypeInfoBest
88 get { return (typeMS == null) ? typeMono : typeMS; }
91 public bool IsDelegate
95 Type typeBest
= TypeInfoBest
;
96 if (typeBest
.IsEnum
|| typeBest
.IsInterface
|| typeBest
.IsValueType
)
98 Type type
= typeBest
.BaseType
;
101 if (type
.FullName
== "System.Delegate")
103 type
= type
.BaseType
;
109 public MissingMember
CreateMember (MemberInfo infoMono
, MemberInfo infoMS
)
111 MemberTypes mt
= (infoMono
!= null) ? infoMono
.MemberType
: infoMS
.MemberType
;
115 case MemberTypes
.Method
:
116 mm
= new MissingMethod (infoMono
, infoMS
);
118 case MemberTypes
.Property
:
119 mm
= new MissingProperty (infoMono
, infoMS
);
121 case MemberTypes
.Event
:
122 mm
= new MissingEvent (infoMono
, infoMS
);
124 case MemberTypes
.Field
:
125 mm
= new MissingField (infoMono
, infoMS
);
127 case MemberTypes
.Constructor
:
128 mm
= new MissingConstructor (infoMono
, infoMS
);
130 case MemberTypes
.NestedType
:
131 mm
= new MissingNestedType (infoMono
, infoMS
);
134 throw new Exception ("Unexpected MemberType: " + mt
.ToString());
141 public void AddMember (MissingMember mm
)
143 switch (mm
.Info
.MemberType
)
145 case MemberTypes
.Method
:
146 nsMethods
.AddChildren (mm
.Status
);
149 case MemberTypes
.Property
:
150 nsProperties
.AddChildren (mm
.Status
);
151 rgProperties
.Add (mm
);
153 case MemberTypes
.Event
:
154 nsEvents
.AddChildren (mm
.Status
);
157 case MemberTypes
.Field
:
158 nsFields
.AddChildren (mm
.Status
);
161 case MemberTypes
.Constructor
:
162 nsConstructors
.AddChildren (mm
.Status
);
163 rgConstructors
.Add (mm
);
165 case MemberTypes
.NestedType
:
166 nsNestedTypes
.AddChildren (mm
.Status
);
167 rgNestedTypes
.Add (mm
);
170 throw new Exception ("Unexpected MemberType: " + mm
.Info
.ToString());
174 public void AddMember (MemberInfo infoMono
, MemberInfo infoMS
)
176 AddMember (CreateMember (infoMono
, infoMS
));
179 public override XmlElement
CreateXML (XmlDocument doc
)
181 XmlElement eltClass
= base.CreateXML (doc
);
182 XmlElement eltMember
;
184 eltMember
= MissingBase
.CreateMemberCollectionElement ("methods", rgMethods
, nsMethods
, doc
);
185 if (eltMember
!= null)
186 eltClass
.AppendChild (eltMember
);
188 eltMember
= MissingBase
.CreateMemberCollectionElement ("properties", rgProperties
, nsProperties
, doc
);
189 if (eltMember
!= null)
190 eltClass
.AppendChild (eltMember
);
192 eltMember
= MissingBase
.CreateMemberCollectionElement ("events", rgEvents
, nsEvents
, doc
);
193 if (eltMember
!= null)
194 eltClass
.AppendChild (eltMember
);
196 eltMember
= MissingBase
.CreateMemberCollectionElement ("fields", rgFields
, nsFields
, doc
);
197 if (eltMember
!= null)
198 eltClass
.AppendChild (eltMember
);
200 eltMember
= MissingBase
.CreateMemberCollectionElement ("constructors", rgConstructors
, nsConstructors
, doc
);
201 if (eltMember
!= null)
202 eltClass
.AppendChild (eltMember
);
204 eltMember
= MissingBase
.CreateMemberCollectionElement ("nestedTypes", rgNestedTypes
, nsNestedTypes
, doc
);
205 if (eltMember
!= null)
206 eltClass
.AppendChild (eltMember
);
208 eltMember
= MissingBase
.CreateMemberCollectionElement ("interfaces", rgInterfaces
, nsInterfaces
, doc
);
209 if (eltMember
!= null)
210 eltClass
.AppendChild (eltMember
);
215 public override NodeStatus
Analyze ()
217 Hashtable htMono
= new Hashtable ();
218 if (typeMono
!= null)
220 ArrayList rgIgnoreMono
= new ArrayList ();
221 foreach (MemberInfo miMono
in typeMono
.GetMembers (BindingFlags
.Static
| BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
))
223 if (typeMono
== miMono
.DeclaringType
)
225 string strName
= MissingMember
.GetUniqueName (miMono
);
226 htMono
.Add (strName
, miMono
);
228 // ignore any property/event accessors
229 if (miMono
.MemberType
== MemberTypes
.Property
)
231 PropertyInfo pi
= (PropertyInfo
) miMono
;
232 MemberInfo miGet
= pi
.GetGetMethod ();
234 rgIgnoreMono
.Add (miGet
);
235 MemberInfo miSet
= pi
.GetSetMethod ();
237 rgIgnoreMono
.Add (miSet
);
239 else if (miMono
.MemberType
== MemberTypes
.Event
)
241 EventInfo ei
= (EventInfo
) miMono
;
242 MemberInfo miAdd
= ei
.GetAddMethod ();
244 rgIgnoreMono
.Add (miAdd
);
245 MemberInfo miRemove
= ei
.GetRemoveMethod ();
246 if (miRemove
!= null)
247 rgIgnoreMono
.Add (miRemove
);
248 MemberInfo miRaise
= ei
.GetRaiseMethod ();
250 rgIgnoreMono
.Add (miRaise
);
254 foreach (MemberInfo miIgnore
in rgIgnoreMono
)
255 htMono
.Remove (MissingMember
.GetUniqueName (miIgnore
));
257 Hashtable htMethodsMS
= new Hashtable ();
260 ICollection colMembersMS
= typeMS
.GetMembers (BindingFlags
.Static
| BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
261 Hashtable htIgnoreMS
= new Hashtable ();
262 foreach (MemberInfo miMS
in colMembersMS
)
264 // ignore any property/event accessors
265 if (miMS
.MemberType
== MemberTypes
.Property
)
267 PropertyInfo pi
= (PropertyInfo
) miMS
;
268 MemberInfo miGet
= pi
.GetGetMethod ();
270 htIgnoreMS
.Add (miGet
, miMS
);
271 MemberInfo miSet
= pi
.GetSetMethod ();
273 htIgnoreMS
.Add (miSet
, miMS
);
275 else if (miMS
.MemberType
== MemberTypes
.Event
)
277 EventInfo ei
= (EventInfo
) miMS
;
278 MemberInfo miAdd
= ei
.GetAddMethod ();
280 htIgnoreMS
.Add (miAdd
, miMS
);
281 MemberInfo miRemove
= ei
.GetRemoveMethod ();
282 if (miRemove
!= null)
283 htIgnoreMS
.Add (miRemove
, miMS
);
284 MemberInfo miRaise
= ei
.GetRaiseMethod ();
286 htIgnoreMS
.Add (miRaise
, miMS
);
289 foreach (MemberInfo miMS
in colMembersMS
)
291 if (miMS
!= null && miMS
.DeclaringType
== typeMS
&& !htIgnoreMS
.Contains (miMS
))
293 string strNameUnique
= MissingMember
.GetUniqueName (miMS
);
294 MemberInfo miMono
= (MemberInfo
) htMono
[strNameUnique
];
296 MissingMember mm
= CreateMember (miMono
, miMS
);
298 bool fVisibleMS
= IsVisible (miMS
);
306 if (miMono
.MemberType
!= miMS
.MemberType
)
308 //AddMember (null, miMS);
309 //MissingMember mm2 = CreateMember (miMono, null);
310 //mm2.Status.AddWarning ("MemberType mismatch, is: '" + miMono.MemberType.ToString () + "' [should be: '" + miMS.MemberType.ToString ()+"']");
312 mm
.Status
.AddWarning ("MemberType mismatch, is: '" + miMono
.MemberType
.ToString () + "' [should be: '" + miMS
.MemberType
.ToString ()+"']");
315 else if (fVisibleMS
|| IsVisible (miMono
))
320 htMono
.Remove (strNameUnique
);
323 switch (miMS
.MemberType
)
325 case MemberTypes
.Method
:
327 string strNameMSFull
= miMS
.ToString ();
328 int ichMS
= strNameMSFull
.IndexOf (' ');
329 string strNameMS
= strNameMSFull
.Substring (ichMS
+ 1);
330 if (!htMethodsMS
.Contains (strNameMS
))
331 htMethodsMS
.Add (strNameMSFull
.Substring (ichMS
+ 1), miMS
);
338 foreach (MemberInfo miMono
in htMono
.Values
)
340 if (IsVisible (miMono
))
342 MissingMember mm
= CreateMember (miMono
, null);
343 switch (miMono
.MemberType
)
345 case MemberTypes
.Method
:
347 string strNameMonoFull
= miMono
.ToString ();
348 int ichMono
= strNameMonoFull
.IndexOf (' ');
349 string strNameMono
= strNameMonoFull
.Substring (ichMono
+ 1);
350 MemberInfo miMS
= (MemberInfo
) htMethodsMS
[strNameMono
];
353 string strNameMSFull
= miMS
.ToString ();
354 int ichMS
= strNameMSFull
.IndexOf (' ');
355 string strReturnTypeMS
= strNameMSFull
.Substring (0, ichMS
);
356 string strReturnTypeMono
= strNameMonoFull
.Substring (0, ichMono
);
357 mm
.Status
.AddWarning ("Return type mismatch, is: '"+strReturnTypeMono
+"' [should be: '"+strReturnTypeMS
+"']");
358 //Console.WriteLine ("WARNING: Return type mismatch on "+miMS.DeclaringType.FullName+"."+strNameMono+", is: '"+strReturnTypeMono+"' [should be: '"+strReturnTypeMS+"']");
367 // compare the attributes
368 rgAttributes
= new ArrayList ();
369 nsAttributes
= MissingAttribute
.AnalyzeAttributes (
370 (typeMono
== null) ? null : typeMono
.GetCustomAttributes (false),
371 ( typeMS
== null) ? null : typeMS
.GetCustomAttributes (false),
374 rgInterfaces
= new ArrayList ();
375 if (typeMono
!= null && typeMS
!= null)
377 // compare base types
378 string strBaseMono
= (typeMono
.BaseType
== null) ? null : typeMono
.BaseType
.FullName
;
379 string strBaseMS
= ( typeMS
.BaseType
== null) ? null : typeMS
.BaseType
.FullName
;
380 if (strBaseMono
!= strBaseMS
)
382 m_nodeStatus
.AddWarning ("Base class mismatch, is '"+strBaseMono
+"' [should be: '"+strBaseMS
+"']");
383 //Console.WriteLine ("WARNING: Base class mismatch on "+typeMono.FullName+", is: '"+strBaseMono+"' [should be: '"+strBaseMS+"']");
386 // compare the interfaces
387 Hashtable htInterfacesMono
= new Hashtable ();
388 Type
[] rgInterfacesMono
= typeMono
.GetInterfaces ();
389 foreach (Type ifaceMono
in rgInterfacesMono
)
391 if (ifaceMono
!= null)
393 string strName
= ifaceMono
.FullName
;
394 htInterfacesMono
.Add (strName
, ifaceMono
);
397 Type
[] rgInterfacesMS
= typeMS
.GetInterfaces ();
398 foreach (Type ifaceMS
in rgInterfacesMS
)
402 string strName
= ifaceMS
.FullName
;
403 Type ifaceMono
= (Type
) htInterfacesMono
[strName
];
404 MissingInterface mi
= new MissingInterface (ifaceMono
, ifaceMS
);
406 rgInterfaces
.Add (mi
);
407 if (ifaceMono
!= null)
408 htInterfacesMono
.Remove (strName
);
409 nsInterfaces
.AddChildren (mi
.Status
);
412 foreach (Type ifaceMono
in htInterfacesMono
.Values
)
414 MissingInterface mi
= new MissingInterface (ifaceMono
, null);
416 rgInterfaces
.Add (mi
);
417 //Console.WriteLine ("WARNING: additional interface on "+typeMono.FullName+": '"+ifaceMono.FullName+"'");
418 nsInterfaces
.AddChildren (mi
.Status
);
421 // serializable attribute
422 AddFakeAttribute (typeMono
.IsSerializable
, typeMS
.IsSerializable
, "System.SerializableAttribute");
423 AddFakeAttribute (typeMono
.IsAutoLayout
, typeMS
.IsAutoLayout
, "System.AutoLayoutAttribute");
424 AddFakeAttribute (typeMono
.IsExplicitLayout
, typeMS
.IsExplicitLayout
, "System.ExplicitLayoutAttribute");
425 AddFakeAttribute (typeMono
.IsLayoutSequential
, typeMS
.IsLayoutSequential
, "System.SequentialLayoutAttribute");
427 Accessibility accessibilityMono
= GetAccessibility (typeMono
);
428 Accessibility accessibilityMS
= GetAccessibility (typeMS
);
429 if (accessibilityMono
!= accessibilityMS
)
430 m_nodeStatus
.AddWarning ("Should be "+AccessibilityToString (accessibilityMono
));
432 AddFlagWarning (typeMono
.IsSealed
, typeMS
.IsSealed
, "sealed");
433 AddFlagWarning (typeMono
.IsAbstract
, typeMS
.IsAbstract
, "abstract");
436 // sum up the sub-sections
437 m_nodeStatus
.Add (nsAttributes
);
438 m_nodeStatus
.Add (nsMethods
);
439 m_nodeStatus
.Add (nsProperties
);
440 m_nodeStatus
.Add (nsEvents
);
441 m_nodeStatus
.Add (nsFields
);
442 m_nodeStatus
.Add (nsConstructors
);
443 m_nodeStatus
.Add (nsNestedTypes
);
444 m_nodeStatus
.Add (nsInterfaces
);
449 static bool IsVisible (MemberInfo mi
)
451 // this is just embarrasing, couldn't they have virtualized this?
452 switch (mi
.MemberType
)
454 case MemberTypes
.Constructor
:
455 case MemberTypes
.Method
:
456 return !((MethodBase
) mi
).IsPrivate
&& !((MethodBase
) mi
).IsFamilyAndAssembly
&& !((MethodBase
) mi
).IsAssembly
;
457 case MemberTypes
.Field
:
458 return !((FieldInfo
) mi
).IsPrivate
&& !((FieldInfo
) mi
).IsFamilyAndAssembly
&& !((FieldInfo
) mi
).IsAssembly
;
459 case MemberTypes
.NestedType
:
460 return !((Type
) mi
).IsNestedPrivate
&& !((Type
) mi
).IsNestedAssembly
&& !((Type
) mi
).IsNestedFamANDAssem
;
461 case MemberTypes
.Property
: // great, now we have to look at the methods
462 PropertyInfo pi
= (PropertyInfo
) mi
;
463 MethodInfo miAccessor
= pi
.GetGetMethod ();
464 if (miAccessor
== null)
465 miAccessor
= pi
.GetSetMethod ();
466 if (miAccessor
== null)
468 return IsVisible (miAccessor
);
469 case MemberTypes
.Event
: // ditto
470 EventInfo ei
= (EventInfo
) mi
;
471 MethodInfo eiAccessor
= ei
.GetAddMethod ();
472 if (eiAccessor
== null)
473 eiAccessor
= ei
.GetRemoveMethod ();
474 if (eiAccessor
== null)
475 eiAccessor
= ei
.GetRaiseMethod ();
476 if (eiAccessor
== null)
478 return IsVisible (eiAccessor
);
480 throw new Exception ("Missing handler for MemberType: "+mi
.MemberType
.ToString ());
484 static Accessibility
GetAccessibility (Type type
)
487 return Accessibility
.Public
;
488 else if (type
.IsNotPublic
)
489 return Accessibility
.Private
;
490 return MissingMember
.GetAccessibility (type
);