// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2003 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2003-2005 Novell, Inc (http://www.novell.com)
//
using System;
using System.Collections;
+using System.Globalization;
using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
using System.Text;
using System.Xml;
AddAttribute (nassembly, "version", aname.Version.ToString ());
parent.AppendChild (nassembly);
AttributeData.OutputAttributes (document, nassembly, ass.GetCustomAttributes (false));
- Type [] types = ass.GetTypes ();
+ Type [] types = ass.GetExportedTypes ();
if (types == null || types.Length == 0)
return;
continue;
if (t.IsNestedPublic || t.IsNestedAssembly || t.IsNestedFamANDAssem ||
- t.IsNestedFamORAssem || t.IsNestedPrivate)
+ t.IsNestedFamORAssem || t.IsNestedPrivate)
continue;
if (t.DeclaringType != null)
get { return "NoTAG"; }
}
}
-
+
class TypeData : MemberData
{
Type type;
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static |
- BindingFlags.Instance | BindingFlags.DeclaredOnly;
+ BindingFlags.Instance | BindingFlags.DeclaredOnly |
+ BindingFlags.NonPublic;
public TypeData (XmlDocument document, XmlNode parent, Type type)
: base (document, parent, null)
AddAttribute (nclass, "name", type.Name);
string classType = GetClassType (type);
AddAttribute (nclass, "type", classType);
+
if (type.BaseType != null)
- AddAttribute (nclass, "base", type.BaseType.FullName);
+ AddAttribute (nclass, "base", type.BaseType.ToString ());
if (type.IsSealed)
AddAttribute (nclass, "sealed", "true");
+ if (type.IsAbstract)
+ AddAttribute (nclass, "abstract", "true");
+
+ if (type.IsSerializable)
+ AddAttribute (nclass, "serializable", "true");
+
+ string charSet = GetCharSet (type);
+ AddAttribute (nclass, "charset", charSet);
+
+ string layout = GetLayout (type);
+ if (layout != null)
+ AddAttribute (nclass, "layout", layout);
+
parent.AppendChild (nclass);
AttributeData.OutputAttributes (document, nclass, type.GetCustomAttributes (false));
XmlNode ifaces = document.CreateElement ("interfaces", null);
nclass.AppendChild (ifaces);
foreach (Type t in interfaces) {
+ if (!t.IsPublic) {
+ // we're only interested in public interfaces
+ continue;
+ }
XmlNode iface = document.CreateElement ("interface", null);
- AddAttribute (iface, "name", t.FullName);
+ AddAttribute (iface, "name", t.ToString ());
ifaces.AppendChild (iface);
}
}
ArrayList members = new ArrayList ();
- FieldInfo [] fields = type.GetFields (flags);
- if (fields != null && fields.Length > 0) {
- fields = FieldRemoveSpecials (fields);
- if (fields != null) {
- Array.Sort (fields, MemberInfoComparer.Default);
- FieldData fd = new FieldData (document, nclass, fields);
- // Special case for enum fields
- if (classType == "enum") {
- string etype = fields [0].GetType ().FullName;
- AddAttribute (nclass, "enumtype", etype);
- }
-
- members.Add (fd);
+ FieldInfo[] fields = GetFields (type);
+ if (fields.Length > 0) {
+ Array.Sort (fields, MemberInfoComparer.Default);
+ FieldData fd = new FieldData (document, nclass, fields);
+ // Special case for enum fields
+ if (classType == "enum") {
+ string etype = fields [0].GetType ().ToString ();
+ AddAttribute (nclass, "enumtype", etype);
}
+ members.Add (fd);
}
- // No .cctor
- ConstructorInfo [] ctors = type.GetConstructors (flags);
-
+ ConstructorInfo [] ctors = GetConstructors (type);
if (ctors.Length > 0) {
- Array.Sort (ctors, MethodBaseComparer.Default);
+ Array.Sort (ctors, MemberInfoComparer.Default);
members.Add (new ConstructorData (document, nclass, ctors));
}
- PropertyInfo [] props = type.GetProperties (flags);
- if (props != null && props.Length > 0) {
- Array.Sort (props, MemberInfoComparer.Default);
- members.Add (new PropertyData (document, nclass, props));
+ PropertyInfo[] properties = GetProperties (type);
+ if (properties.Length > 0) {
+ Array.Sort (properties, MemberInfoComparer.Default);
+ members.Add (new PropertyData (document, nclass, properties));
}
- EventInfo [] events = type.GetEvents (flags);
- if (events != null && events.Length > 0) {
+ EventInfo [] events = GetEvents (type);
+ if (events.Length > 0) {
Array.Sort (events, MemberInfoComparer.Default);
members.Add (new EventData (document, nclass, events));
}
- MethodInfo [] methods = type.GetMethods (flags);
- if (methods != null && methods.Length > 0) {
- methods = MethodRemoveSpecials (methods);
- if (methods != null) {
- Array.Sort (methods, MethodBaseComparer.Default);
- members.Add (new MethodData (document, nclass, methods));
- }
+ MethodInfo [] methods = GetMethods (type);
+ if (methods.Length > 0) {
+ Array.Sort (methods, MemberInfoComparer.Default);
+ members.Add (new MethodData (document, nclass, methods));
}
foreach (MemberData md in members)
if (member != type)
throw new InvalidOperationException ("odd");
- return ((int) type.Attributes).ToString ();
+ return ((int) type.Attributes).ToString (CultureInfo.InvariantCulture);
}
- static MethodInfo [] MethodRemoveSpecials (MethodInfo [] methods)
+ public static bool MustDocumentMethod(MethodBase method)
{
- ArrayList list = null;
- foreach (MethodInfo method in methods) {
- if (method.IsSpecialName)
- continue;
+ // All other methods
+ return (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly);
+ }
- if (list == null)
- list = new ArrayList ();
+ static string GetClassType (Type t)
+ {
+ if (t.IsEnum)
+ return "enum";
- list.Add (method);
- }
+ if (t.IsValueType)
+ return "struct";
+
+ if (t.IsInterface)
+ return "interface";
- if (list == null)
- return null;
+ if (typeof (Delegate).IsAssignableFrom (t))
+ return "delegate";
- return (MethodInfo []) list.ToArray (typeof (MethodInfo));
+ return "class";
}
- static FieldInfo [] FieldRemoveSpecials (FieldInfo [] fields)
+ private static string GetCharSet (Type type)
{
- ArrayList list = null;
+ if (type.IsAnsiClass)
+ return CharSet.Ansi.ToString (CultureInfo.InvariantCulture);
+
+ if (type.IsAutoClass)
+ return CharSet.Auto.ToString (CultureInfo.InvariantCulture);
+
+ if (type.IsUnicodeClass)
+ return CharSet.Unicode.ToString (CultureInfo.InvariantCulture);
+
+ return CharSet.None.ToString (CultureInfo.InvariantCulture);
+ }
+
+ private static string GetLayout (Type type)
+ {
+ if (type.IsAutoLayout)
+ return LayoutKind.Auto.ToString (CultureInfo.InvariantCulture);
+
+ if (type.IsExplicitLayout)
+ return LayoutKind.Explicit.ToString (CultureInfo.InvariantCulture);
+
+ if (type.IsLayoutSequential)
+ return LayoutKind.Sequential.ToString (CultureInfo.InvariantCulture);
+
+ return null;
+ }
+
+ private FieldInfo[] GetFields (Type type)
+ {
+ ArrayList list = new ArrayList ();
+
+ FieldInfo[] fields = type.GetFields (flags);
foreach (FieldInfo field in fields) {
if (field.IsSpecialName)
continue;
- if (list == null)
- list = new ArrayList ();
+ // we're only interested in public or protected members
+ if (!field.IsPublic && !field.IsFamily && !field.IsFamilyOrAssembly)
+ continue;
list.Add (field);
}
- if (list == null)
- return null;
+ return (FieldInfo[]) list.ToArray (typeof (FieldInfo));
+ }
+
+ internal static PropertyInfo[] GetProperties (Type type)
+ {
+ ArrayList list = new ArrayList ();
+
+ PropertyInfo[] properties = type.GetProperties (flags);
+ foreach (PropertyInfo property in properties) {
+ MethodInfo getMethod = null;
+ MethodInfo setMethod = null;
+
+ if (property.CanRead) {
+ try { getMethod = property.GetGetMethod (true); }
+ catch (System.Security.SecurityException) { }
+ }
+ if (property.CanWrite) {
+ try { setMethod = property.GetSetMethod (true); }
+ catch (System.Security.SecurityException) { }
+ }
+
+ bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod);
+ bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod);
+
+ // if neither the getter or setter should be documented, then
+ // skip the property
+ if (!hasGetter && !hasSetter) {
+ continue;
+ }
+
+ list.Add (property);
+ }
- return (FieldInfo []) list.ToArray (typeof (FieldInfo));
+ return (PropertyInfo[]) list.ToArray (typeof (PropertyInfo));
}
- static string GetClassType (Type t)
+ private MethodInfo[] GetMethods (Type type)
{
- if (t.IsEnum)
- return "enum";
+ ArrayList list = new ArrayList ();
- if (t.IsValueType)
- return "struct";
+ MethodInfo[] methods = type.GetMethods (flags);
+ foreach (MethodInfo method in methods) {
+ if (method.IsSpecialName)
+ continue;
- if (t.IsInterface)
- return "interface";
+ // we're only interested in public or protected members
+ if (!MustDocumentMethod(method))
+ continue;
- if (typeof (Delegate).IsAssignableFrom (t))
- return "delegate";
+ list.Add (method);
+ }
- return "class";
+ return (MethodInfo[]) list.ToArray (typeof (MethodInfo));
+ }
+
+ private ConstructorInfo[] GetConstructors (Type type)
+ {
+ ArrayList list = new ArrayList ();
+
+ ConstructorInfo[] ctors = type.GetConstructors (flags);
+ foreach (ConstructorInfo constructor in ctors) {
+ // we're only interested in public or protected members
+ if (!constructor.IsPublic && !constructor.IsFamily && !constructor.IsFamilyOrAssembly)
+ continue;
+
+ list.Add (constructor);
+ }
+
+ return (ConstructorInfo[]) list.ToArray (typeof (ConstructorInfo));
+ }
+
+ private EventInfo[] GetEvents (Type type)
+ {
+ ArrayList list = new ArrayList ();
+
+ EventInfo[] events = type.GetEvents (flags);
+ foreach (EventInfo eventInfo in events) {
+ MethodInfo addMethod = eventInfo.GetAddMethod (true);
+
+ if (addMethod == null || !MustDocumentMethod (addMethod))
+ continue;
+
+ list.Add (eventInfo);
+ }
+
+ return (EventInfo[]) list.ToArray (typeof (EventInfo));
}
}
protected override string GetMemberAttributes (MemberInfo member)
{
FieldInfo field = (FieldInfo) member;
- return ((int) field.Attributes).ToString ();
+ return ((int) field.Attributes).ToString (CultureInfo.InvariantCulture);
}
protected override void AddExtraData (XmlNode p, MemberInfo member)
{
base.AddExtraData (p, member);
FieldInfo field = (FieldInfo) member;
- AddAttribute (p, "fieldtype", field.FieldType.FullName);
+ AddAttribute (p, "fieldtype", field.FieldType.ToString ());
+
+ if (field.IsLiteral) {
+ object value = field.GetValue (null);
+ string stringValue = null;
+ if (value is Enum) {
+ // FIXME: when Mono bug #60090 has been
+ // fixed, we should just be able to use
+ // Convert.ToString
+ stringValue = ((Enum) value).ToString ("D", CultureInfo.InvariantCulture);
+ } else {
+ stringValue = Convert.ToString (value, CultureInfo.InvariantCulture);
+ }
+
+ if (stringValue != null)
+ AddAttribute (p, "value", stringValue);
+ }
}
public override string ParentTag {
{
base.AddExtraData (p, member);
PropertyInfo prop = (PropertyInfo) member;
- AddAttribute (p, "ptype", prop.PropertyType.FullName);
- MethodInfo _get = prop.GetGetMethod ();
- MethodInfo _set = prop.GetSetMethod ();
- bool haveGet = (_get != null);
- bool haveSet = (_set != null);
+ Type t = prop.PropertyType;
+ AddAttribute (p, "ptype", prop.PropertyType.ToString ());
+ MethodInfo _get = prop.GetGetMethod (true);
+ MethodInfo _set = prop.GetSetMethod (true);
+ bool haveGet = (_get != null && TypeData.MustDocumentMethod(_get));
+ bool haveSet = (_set != null && TypeData.MustDocumentMethod(_set));
MethodInfo [] methods;
if (haveGet && haveSet) {
protected override string GetMemberAttributes (MemberInfo member)
{
PropertyInfo prop = (PropertyInfo) member;
- return ((int) prop.Attributes).ToString ();
+ return ((int) prop.Attributes).ToString (CultureInfo.InvariantCulture);
}
public override string ParentTag {
protected override string GetMemberAttributes (MemberInfo member)
{
EventInfo evt = (EventInfo) member;
- return ((int) evt.Attributes).ToString ();
+ return ((int) evt.Attributes).ToString (CultureInfo.InvariantCulture);
}
protected override void AddExtraData (XmlNode p, MemberInfo member)
{
base.AddExtraData (p, member);
EventInfo evt = (EventInfo) member;
- AddAttribute (p, "eventtype", evt.EventHandlerType.FullName);
+ AddAttribute (p, "eventtype", evt.EventHandlerType.ToString ());
}
public override string ParentTag {
protected override string GetMemberAttributes (MemberInfo member)
{
MethodBase method = (MethodBase) member;
- return ((int) method.Attributes).ToString ();
+ return ((int)( method.Attributes & ~MethodAttributes.ReservedMask)).ToString (CultureInfo.InvariantCulture);
}
protected override void AddExtraData (XmlNode p, MemberInfo member)
{
base.AddExtraData (p, member);
+
+ ParameterData parms = new ParameterData (document, p,
+ ((MethodBase) member).GetParameters ());
+ parms.DoOutput ();
+
if (!(member is MethodInfo))
return;
-
+
MethodInfo method = (MethodInfo) member;
- AddAttribute (p, "returntype", method.ReturnType.FullName);
+ AddAttribute (p, "returntype", method.ReturnType.ToString ());
+
+ AttributeData.OutputAttributes (document, p,
+ method.ReturnTypeCustomAttributes.GetCustomAttributes (false));
}
public override bool NoMemberAttributes {
}
}
+ class ParameterData : BaseData
+ {
+ private ParameterInfo[] parameters;
+
+ public ParameterData (XmlDocument document, XmlNode parent, ParameterInfo[] parameters)
+ : base (document, parent)
+ {
+ this.parameters = parameters;
+ }
+
+ public override void DoOutput ()
+ {
+ XmlNode parametersNode = document.CreateElement ("parameters", null);
+ parent.AppendChild (parametersNode);
+
+ foreach (ParameterInfo parameter in parameters) {
+ XmlNode paramNode = document.CreateElement ("parameter", null);
+ parametersNode.AppendChild (paramNode);
+ AddAttribute (paramNode, "name", parameter.Name);
+ AddAttribute (paramNode, "position", parameter.Position.ToString(CultureInfo.InvariantCulture));
+ AddAttribute (paramNode, "attrib", ((int) parameter.Attributes).ToString());
+
+ string direction = "in";
+
+ if (parameter.ParameterType.IsByRef) {
+ direction = parameter.IsOut ? "out" : "ref";
+ }
+
+ Type t = parameter.ParameterType;
+ AddAttribute (paramNode, "type", t.ToString ());
+
+ if (parameter.IsOptional) {
+ AddAttribute (paramNode, "optional", "true");
+ if (parameter.DefaultValue != System.DBNull.Value)
+ AddAttribute (paramNode, "defaultValue", (parameter.DefaultValue == null) ? "NULL" : parameter.DefaultValue.ToString ());
+ }
+
+ if (direction != "in")
+ AddAttribute (paramNode, "direction", direction);
+
+ AttributeData.OutputAttributes (document, paramNode, parameter.GetCustomAttributes (false));
+ }
+ }
+ }
+
class AttributeData : BaseData
{
object [] atts;
+ string target;
- AttributeData (XmlDocument doc, XmlNode parent, object [] attributes)
+ AttributeData (XmlDocument doc, XmlNode parent, object[] attributes, string target)
: base (doc, parent)
{
- this.atts = attributes;
+ atts = attributes;
+ this.target = target;
+ }
+
+ AttributeData (XmlDocument doc, XmlNode parent, object [] attributes)
+ : this (doc, parent, attributes, null)
+ {
}
public override void DoOutput ()
if (atts == null || atts.Length == 0)
return;
- XmlNode natts = document.CreateElement ("attributes", null);
- parent.AppendChild (natts);
+ XmlNode natts = parent.SelectSingleNode("attributes");
+ if (natts == null) {
+ natts = document.CreateElement ("attributes", null);
+ parent.AppendChild (natts);
+ }
- Type [] types = new Type [atts.Length];
- for (int i = atts.Length - 1; i >= 0; i--)
- types [i] = atts [i].GetType ();
+ for (int i = 0; i < atts.Length; ++i) {
+ Type t = atts [i].GetType ();
+ if (!t.IsPublic && !t.Name.EndsWith ("TODOAttribute"))
+ continue;
+
+ // we ignore attributes that inherit from SecurityAttribute on purpose as they:
+ // * aren't part of GetCustomAttributes in Fx 1.0/1.1;
+ // * are encoded differently and in a different metadata table; and
+ // * won't ever exactly match MS implementation (from a syntax pov)
+ if (t.IsSubclassOf (typeof (SecurityAttribute)))
+ continue;
- Array.Sort (types, TypeComparer.Default);
- foreach (Type t in types) {
XmlNode node = document.CreateElement ("attribute");
- AddAttribute (node, "name", t.FullName);
+ AddAttribute (node, "name", t.ToString ());
+
+ XmlNode properties = null;
+ foreach (PropertyInfo pi in TypeData.GetProperties (t)) {
+ if (pi.Name == "TypeId")
+ continue;
+
+ if (properties == null) {
+ properties = node.AppendChild (document.CreateElement ("properties"));
+ }
+
+ try {
+ object o = pi.GetValue (atts [i], null);
+
+ XmlNode n = properties.AppendChild (document.CreateElement ("property"));
+ AddAttribute (n, "name", pi.Name);
+
+ if (o == null) {
+ AddAttribute (n, "null", "true");
+ continue;
+ }
+
+ string value = o.ToString ();
+ if (t == typeof (GuidAttribute))
+ value = value.ToUpper ();
+
+ AddAttribute (n, "value", value);
+ }
+ catch (TargetInvocationException) {
+ continue;
+ }
+ }
+
+ if (target != null) {
+ AddAttribute (node, "target", target);
+ }
+
natts.AppendChild (node);
}
}
- public static void OutputAttributes (XmlDocument doc, XmlNode parent, object [] attributes)
+ public static void OutputAttributes (XmlDocument doc, XmlNode parent, object[] attributes)
+ {
+ AttributeData ad = new AttributeData (doc, parent, attributes, null);
+ ad.DoOutput ();
+ }
+
+ public static void OutputAttributes (XmlDocument doc, XmlNode parent, object [] attributes, string target)
{
- AttributeData ad = new AttributeData (doc, parent, attributes);
+ AttributeData ad = new AttributeData (doc, parent, attributes, target);
ad.DoOutput ();
}
+
+ private static bool MustDocumentAttribute (Type attributeType)
+ {
+ // only document MonoTODOAttribute and public attributes
+ return attributeType.Name.EndsWith ("TODOAttribute") || attributeType.IsPublic;
+ }
}
class Parameters
else
modifier = "";
- //TODO: parameter attributes
-
- string type_name = info.ParameterType.ToString ();
+ string type_name = info.ParameterType.ToString ().Replace ('<', '[').Replace ('>', ']');
sb.AppendFormat ("{0}{1}, ", modifier, type_name);
}