[Mono-docs-list] Gtk# docs and the updater
Joshua Tauberer
tauberer@for.net
Thu, 26 Feb 2004 18:19:44 -0500
This is a multi-part message in MIME format.
--------------090302010809020706000207
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Attached is stub.cs, which should probably replace the current updater
program. It has three functions:
1) Creating a new XML file for a particular type. ex:
mono stub.exe --stub Gdk.Rectangle,gdk-sharp > path/to/Rectangle.xml
2) Updating an XML file. Deleted members are removed from the xml file.
New members are added. Each deleted/added member is printed to
stdout. ex:
mono stub.exe --update ../../gtk-sharp/doc/en Gdk.Rectangle,gdk-sharp >
path/to/new/Rectangle.xml
Unfortunately, BindingFlags.IgnoreCase seems to not be working, so I
couldn't quickly add a check to see if the case of the member names changed.
3) Creating a fresh XML file for a particular type, but importing the
Docs nodes from an existing XML file. Unlike (2), this guarantees the
output XML file is properly structured. But, it results in a file
that's got a lot of whitespace differences from the original, which
would make it difficult to make sure that the program hasn't deleted
docs by accident.
ex:
mono stub.exe --regen ../../gtk-sharp/doc/en Gdk.Rectangle,gdk-sharp >
path/to/new/Rectangle.xml
John Luke wrote:
> It would be super sweet if it is capable of updating all the
> monodoc/class/* docs as well. They really need an update, since they
> haven't been updated in ages.
Yup, it could do that.
Good luck to whoever uses this. (Back up all of the docs first!)
--
- Joshua Tauberer
http://taubz.for.net
** Nothing Unreal Exists **
--------------090302010809020706000207
Content-Type: text/c-sharp;
name="stub.cs"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="stub.cs"
using System;
using System.Collections;
using System.Text;
using System.Reflection;
using System.Xml;
public class Stub {
static XmlDocument doc = new XmlDocument();
public static void Main(string[] args) {
if (args.Length == 0) {
Console.WriteLine("Usage: mono stub.exe command");
Console.WriteLine("commands:");
Console.WriteLine("\t--stub type\tCreates a type stub file on stdout.");
Console.WriteLine("\t--update basedir type\tUpdates the file for type to stdout, with the file located in basedir/type.Namespace/type.Name.xml, by adding and removing new members as necessary.");
Console.WriteLine("\t--regen basedir type\tCreates a type stub file on stdout, importing the Docs nodes from the file located in basedir/type.Namespace/type.Name.xml as appropriate.");
return;
}
switch (args[0]) {
case "--stub":
if (args.Length != 2) throw new InvalidOperationException();
DoStubType(args[1]);
break;
case "--update":
if (args.Length != 3) throw new InvalidOperationException();
DoUpdateType(args[1], args[2]);
break;
case "--regen":
if (args.Length != 3) throw new InvalidOperationException();
DoRegenType(args[1], args[2]);
break;
default:
Console.WriteLine("Invalid command. Run with no arguments for help.");
break;
}
}
private static void WriteXml(XmlElement element, System.IO.TextWriter output) {
XmlTextWriter writer = new XmlTextWriter(output);
writer.Formatting = Formatting.Indented;
writer.Indentation = 1;
writer.IndentChar = '\t';
element.WriteTo(writer);
output.WriteLine();
}
public static void DoStubType(string type) {
WriteXml(StubType(type), Console.Out);
}
public static void DoUpdateType(string basepath, string typename) {
Type type = Type.GetType(typename, true);
XmlDocument basefile = new XmlDocument();
basefile.PreserveWhitespace = true;
basefile.Load(basepath + "/" + type.Namespace + "/" + type.Name + ".xml");
XmlElement newfile = StubType(type);
Hashtable seenmembers = new Hashtable();
// Look for deleted members, remember what members are in the file
foreach (XmlElement oldmember in basefile.SelectNodes("Type/Members/Member")) {
MemberInfo oldmember2 = GetMember(type, oldmember);
if (oldmember2 == null) {
// Deleted (or signature changed)
Console.Error.WriteLine("Member Deleted: " + oldmember.SelectSingleNode("MemberSignature/@Value").InnerText);
oldmember.ParentNode.RemoveChild(oldmember);
continue;
}
seenmembers[oldmember2] = 1;
}
XmlNode members = basefile.SelectSingleNode("Type/Members");
foreach (MemberInfo m in type.GetMembers(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance|BindingFlags.DeclaredOnly)) {
if (m is Type) continue;
if (seenmembers.ContainsKey(m)) continue;
XmlElement mm = MakeMember(m);
if (mm == null) continue;
members.AppendChild( basefile.ImportNode(mm, true) );
members.AppendChild( members.OwnerDocument.CreateWhitespace("\n") );
Console.Error.WriteLine("Member Added: " + mm.SelectSingleNode("MemberSignature/@Value").InnerText);
}
WriteXml(basefile.DocumentElement, Console.Out);
}
public static void DoRegenType(string basepath, string typename) {
Type type = Type.GetType(typename, true);
XmlDocument basefile = new XmlDocument();
basefile.PreserveWhitespace = true;
basefile.Load(basepath + "/" + type.Namespace + "/" + type.Name + ".xml");
XmlElement newfile = StubType(type);
// Copy old Type/Docs into new doc
newfile.ReplaceChild(newfile.OwnerDocument.ImportNode(basefile.SelectSingleNode("Type/Docs"), true), newfile.SelectSingleNode("Docs"));
// Copy old Type/Members/Member/Docs into new doc
foreach (XmlElement oldmember in basefile.SelectNodes("Type/Members/Member")) {
XmlElement newmember = FindMatchingMember(type, newfile, oldmember);
if (newmember == null) {
Console.Error.WriteLine("Member Deleted: " + oldmember.SelectSingleNode("MemberSignature/@Value").InnerText);
continue;
}
newmember.ReplaceChild(newmember.OwnerDocument.ImportNode(oldmember.SelectSingleNode("Docs"), true), newmember.SelectSingleNode("Docs"));
}
WriteXml(newfile, Console.Out);
}
// UPDATE HELPER FUNCTIONS
private static XmlElement FindMatchingMember(Type type, XmlElement newfile, XmlElement oldmember) {
MemberInfo oldmember2 = GetMember(type, oldmember);
if (oldmember2 == null) return null;
string membername = oldmember.GetAttribute("MemberName");
foreach (XmlElement newmember in newfile.SelectNodes("Members/Member[@MemberName='" + membername + "']")) {
if (GetMember(type, newmember) == oldmember2) return newmember;
}
return null;
}
private static MemberInfo GetMember(Type type, XmlElement member) {
string membertype = member.SelectSingleNode("MemberType").InnerText;
// Get list of parameter types for member
ArrayList memberparams = new ArrayList();
foreach (XmlElement param in member.SelectNodes("Parameters/Parameter"))
memberparams.Add(param.GetAttribute("Type"));
// Loop through all members in this type with the same name
MemberInfo[] mis = type.GetMember(member.GetAttribute("MemberName"), BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MemberInfo mi in mis) {
if (mi is Type) continue;
if (GetMemberType(mi) != membertype) continue;
ParameterInfo[] pis = null;
if (mi is MethodInfo || mi is ConstructorInfo)
pis = ((MethodBase)mi).GetParameters();
else if (mi is PropertyInfo)
pis = ((PropertyInfo)mi).GetIndexParameters();
if (pis == null)
pis = new ParameterInfo[0];
if (pis.Length != memberparams.Count) continue;
bool good = true;
for (int i = 0; i < pis.Length; i++)
if (pis[i].ParameterType.FullName != (string)memberparams[i]) { good = false; break; }
if (!good) continue;
return mi;
}
return null;
}
// CREATE A STUB OF A DOCUMENTATION FILE
public static XmlElement StubType(string type) {
return StubType(Type.GetType(type, true));
}
public static XmlElement StubType(Type type) {
string typesig = MakeTypeSignature(type);
if (typesig == null) return null; // not publicly visible
XmlElement root = doc.CreateElement("Type");
root.SetAttribute("Name", type.Name);
root.SetAttribute("FullName", type.FullName);
XmlElement sig = doc.CreateElement("TypeSignature");
root.AppendChild(sig);
sig.SetAttribute("Language", "C#");
sig.SetAttribute("Value", typesig);
XmlElement ass = doc.CreateElement("AssemblyInfo");
root.AppendChild(ass);
ass.AppendChild(SimpleElement("AssemblyName", type.Assembly.GetName().Name));
ass.AppendChild(SimpleElement("AssemblyVersion", type.Assembly.GetName().Version.ToString()));
ass.AppendChild(SimpleElement("AssemblyCulture", type.Assembly.GetName().CultureInfo.Name));
XmlElement assattributes = MakeAttributes(type.Assembly);
if (assattributes != null) ass.AppendChild(assattributes);
XmlElement basetype = doc.CreateElement("Base");
root.AppendChild(basetype);
basetype.AppendChild(SimpleElement("BaseTypeName", type.BaseType.FullName));
if (!IsDelegate(type) && !type.IsInterface) {
XmlElement interfaces = doc.CreateElement("Interfaces");
root.AppendChild(interfaces);
foreach (Type i in type.GetInterfaces()) {
XmlElement iface = doc.CreateElement("Interface");
interfaces.AppendChild(iface);
iface.AppendChild(SimpleElement("InterfaceName", i.FullName));
}
}
XmlElement attributes = MakeAttributes(type);
if (attributes != null) root.AppendChild(attributes);
if (IsDelegate(type)) {
root.AppendChild(MakeParameters(type.GetMethod("Invoke").GetParameters()));
root.AppendChild(MakeReturnValue(type.GetMethod("Invoke").ReturnType));
}
if (!IsDelegate(type)) {
XmlElement members = doc.CreateElement("Members");
root.AppendChild(members);
foreach (MemberInfo m in type.GetMembers(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance|BindingFlags.DeclaredOnly)) {
if (m is Type) continue;
XmlElement mm = MakeMember(m);
if (mm == null) continue;
members.AppendChild( mm );
}
}
root.AppendChild(MakeDocNode(null, null, true));
return root;
}
// STUB HELPER FUNCTIONS
private static XmlElement SimpleElement(string name, string val) {
XmlElement e = doc.CreateElement(name);
e.InnerText = val;
return e;
}
private static XmlElement MakeDocNode(ParameterInfo[] parameters, Type returntype, bool returnisreturn) {
XmlElement e = doc.CreateElement("Docs");
e.AppendChild(SimpleElement("summary", "To be added."));
if (parameters != null) {
foreach (ParameterInfo p in parameters) {
XmlElement pe = SimpleElement("param", "To be added.");
pe.SetAttribute("name", p.Name);
e.AppendChild(pe);
}
}
if (returntype != null && returntype != typeof(void)) {
e.AppendChild(SimpleElement(returnisreturn ? "returns" : "value", "To be added."));
}
e.AppendChild(SimpleElement("remarks", "To be added."));
return e;
}
private static XmlElement MakeAttributes(ICustomAttributeProvider attributes) {
object[] at = attributes.GetCustomAttributes(false);
if (at.Length == 0) return null;
bool b = false;
XmlElement e = doc.CreateElement("Attributes");
foreach (Attribute a in at) {
if (GetTypeVisibility(a.GetType().Attributes) == null) continue; // hide non-visible attributes
b = true;
ArrayList fields = new ArrayList();
foreach (PropertyInfo f in a.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance)) {
if (f.Name == "TypeId") continue;
object v = f.GetValue(a, null);
if (v == null) v = "null";
else if (v is string) v = "\"" + v + "\"";
else if (v is Type) v = "typeof(" + ((Type)v).FullName + ")";
else if (v is Enum) v = v.GetType().FullName + "." + v;
fields.Add(f.Name + "=" + v);
}
string a2 = String.Join(", ", (string[])fields.ToArray(typeof(string)));
if (a2 != "") a2 = "(" + a2 + ")";
XmlElement ae = doc.CreateElement("Attribute");
e.AppendChild(ae);
string name = a.GetType().FullName;
if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length-"Attribute".Length);
ae.AppendChild( SimpleElement("AttributeName", name + a2) );
}
if (!b) return null;
return e;
}
private static XmlElement MakeParameters(ParameterInfo[] parameters) {
XmlElement e = doc.CreateElement("Parameters");
foreach (ParameterInfo p in parameters) {
XmlElement pe = doc.CreateElement("Parameter");
e.AppendChild(pe);
pe.SetAttribute("Name", p.Name);
pe.SetAttribute("Type", p.ParameterType.FullName);
if (p.ParameterType.IsByRef) {
if (p.IsOut) pe.SetAttribute("RefType", "out");
else pe.SetAttribute("RefType", "ref");
}
XmlElement attributes = MakeAttributes(p);
if (attributes != null) pe.AppendChild(attributes);
}
return e;
}
private static XmlElement MakeParameters(MemberInfo mi) {
if (mi is ConstructorInfo) return MakeParameters(((ConstructorInfo)mi).GetParameters());
if (mi is MethodInfo) return MakeParameters(((MethodInfo)mi).GetParameters());
if (mi is PropertyInfo) {
ParameterInfo[] parameters = ((PropertyInfo)mi).GetIndexParameters();
if (parameters.Length > 0)
return MakeParameters(parameters);
else
return null;
}
if (mi is FieldInfo) return null;
if (mi is EventInfo) return null;
throw new ArgumentException();
}
private static XmlElement MakeReturnValue(Type type, ICustomAttributeProvider attributes) {
XmlElement e = doc.CreateElement("ReturnValue");
e.AppendChild( SimpleElement("ReturnType", type.FullName) );
if (attributes != null) {
XmlElement a = MakeAttributes(attributes);
if (a != null) e.AppendChild(a);
}
return e;
}
private static XmlElement MakeReturnValue(MemberInfo mi) {
if (mi is ConstructorInfo) return null;
if (mi is MethodInfo) return MakeReturnValue(((MethodInfo)mi).ReturnType, ((MethodInfo)mi).ReturnTypeCustomAttributes);
if (mi is PropertyInfo) return MakeReturnValue(((PropertyInfo)mi).PropertyType, null);
if (mi is FieldInfo) return MakeReturnValue(((FieldInfo)mi).FieldType, null);
if (mi is EventInfo) return MakeReturnValue(((EventInfo)mi).EventHandlerType, null);
throw new ArgumentException();
}
private static XmlElement MakeMember(MemberInfo mi) {
string sigs = MakeMemberSignature(mi);
if (sigs == null) return null; // not publicly visible
// no documentation for property/event accessors. Is there a better way of doing this?
if (mi.Name.StartsWith("get_")) return null;
if (mi.Name.StartsWith("set_")) return null;
if (mi.Name.StartsWith("add_")) return null;
if (mi.Name.StartsWith("remove_")) return null;
if (mi.Name.StartsWith("raise_")) return null;
XmlElement me = doc.CreateElement("Member");
me.SetAttribute("MemberName", mi.Name);
XmlElement sig = doc.CreateElement("MemberSignature");
me.AppendChild(sig);
sig.SetAttribute("Language", "C#");
sig.SetAttribute("Value", sigs);
me.AppendChild( SimpleElement("MemberType", GetMemberType(mi)) );
XmlElement a = MakeAttributes(mi);
if (a != null) me.AppendChild(a);
XmlElement retval = MakeReturnValue(mi);
if (retval != null) me.AppendChild(retval);
XmlElement parameters = MakeParameters(mi);
if (parameters != null) me.AppendChild(parameters);
if (mi is FieldInfo && (((FieldInfo)mi).IsLiteral || (((FieldInfo)mi).IsStatic && ((FieldInfo)mi).IsInitOnly))) {
object val = ((FieldInfo)mi).GetValue(null);
if (val is IConvertible)
me.AppendChild( SimpleElement("MemberValue", ((IConvertible)val).ToString(null)) );
}
if (mi is MethodInfo)
me.AppendChild(MakeDocNode(((MethodInfo)mi).GetParameters(), ((MethodInfo)mi).ReturnType, true));
else if (mi is ConstructorInfo)
me.AppendChild(MakeDocNode(((ConstructorInfo)mi).GetParameters(), null, false));
else if (mi is PropertyInfo)
me.AppendChild(MakeDocNode(((PropertyInfo)mi).GetIndexParameters(), ((PropertyInfo)mi).PropertyType, false));
else
me.AppendChild(MakeDocNode(null, null, false));
return me;
}
static bool IsDelegate(Type type) {
return typeof(System.Delegate).IsAssignableFrom (type) && !type.IsAbstract;
}
/// SIGNATURE GENERATION FUNCTIONS
static string GetTypeKind (Type t) {
if (t.IsEnum) return "enum";
if (t.IsClass) return "class";
if (t.IsInterface) return "interface";
if (t.IsValueType) return "struct";
throw new ArgumentException();
}
static string GetTypeVisibility (TypeAttributes ta) {
switch (ta & TypeAttributes.VisibilityMask){
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
return "public";
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
return "protected";
default:
return null;
}
}
static string MakeTypeSignature (Type type) {
StringBuilder sig = new StringBuilder();
string visibility = GetTypeVisibility(type.Attributes);
if (visibility == null) return null;
sig.Append(visibility);
sig.Append(" ");
if (type.IsAbstract) sig.Append("abstract ");
if (type.IsSealed && !IsDelegate(type)) sig.Append("sealed ");
if (IsDelegate(type)) {
MethodInfo invoke = type.GetMethod ("Invoke");
string arguments = GetMethodParameters(invoke.GetParameters());
string return_value = ConvertCTSName(invoke.ReturnType.FullName);
sig.Append(return_value);
sig.Append(" ");
sig.Append(type.Name);
sig.Append("(");
sig.Append(arguments);
sig.Append(")");
return sig.ToString();
}
sig.Append(GetTypeKind(type));
sig.Append(" ");
sig.Append(type.Name);
if (!type.IsValueType && !type.IsEnum) {
if ((type.BaseType != null && type.BaseType != typeof(object)) || type.GetInterfaces().Length > 0)
sig.Append(" : ");
if (type.BaseType != null && type.BaseType != typeof(object)) {
sig.Append(type.BaseType.FullName);
if (type.GetInterfaces().Length > 0)
sig.Append(", ");
}
Type [] interfaces = type.GetInterfaces ();
for (int i = 0; i < interfaces.Length; i ++){
if (i != 0) sig.Append(", ");
sig.Append(interfaces [i].FullName);
}
}
return sig.ToString();
}
static string GetFieldVisibility (FieldInfo field) {
if (field.IsPublic) return "public";
if (field.IsFamily) return "protected";
return null;
}
static string MakeFieldSignature (FieldInfo field) {
string visibility = GetFieldVisibility (field);
if (visibility == null) return null;
string type = ConvertCTSName (field.FieldType.FullName);
string modifiers = String.Empty;
if (field.IsStatic) modifiers += " static";
if (field.IsInitOnly) modifiers += " readonly";
if (field.IsLiteral) modifiers += " const";
return String.Format ("{0}{1} {2} {3}",
visibility, modifiers, type, field.Name);
}
static string GetMethodVisibility (MethodBase method) {
if (method.IsPublic) return "public";
if (method.IsFamily) return "protected";
return null;
}
static string GetMethodParameters (ParameterInfo[] pi) {
if (pi.Length == 0) return "";
StringBuilder sb = new StringBuilder ();
int i = 0;
string modifier;
foreach (ParameterInfo parameter in pi) {
if (i != 0) sb.Append (", ");
if (parameter.ParameterType.IsByRef) {
if (parameter.IsOut) sb.Append("out ");
else sb.Append("ref ");
}
string param = ConvertCTSName (parameter.ParameterType.FullName, parameter.ParameterType.IsByRef);
sb.Append (param);
sb.Append (" ");
sb.Append (parameter.Name);
i++;
}
return sb.ToString();
}
static string MakeMethodSignature (MethodInfo method) {
string visibility = GetMethodVisibility (method);
if (visibility == null)
return null;
string modifiers = String.Empty;
if (method.IsStatic) modifiers += " static";
if (method.IsVirtual) {
if ((method.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual";
else modifiers += " override";
}
if (method.IsAbstract) modifiers += " abstract";
if (method.IsFinal) modifiers += " sealed";
string return_type = ConvertCTSName (method.ReturnType.FullName);
string parameters = GetMethodParameters (method.GetParameters());
string method_name = method.Name;
// operators, default accessors need name rewriting
return String.Format ("{0}{1} {2} {3}({4})",
visibility, modifiers, return_type, method_name, parameters);
}
static string MakeConstructorSignature (ConstructorInfo constructor) {
string visibility = GetMethodVisibility (constructor);
if (visibility == null)
return null;
string name = constructor.DeclaringType.Name;
string parameters = GetMethodParameters (constructor.GetParameters());
return String.Format ("{0} {1}({2})",
visibility, name, parameters);
}
static string MakePropertySignature (PropertyInfo property) {
// pick an accessor
MethodBase method = property.GetSetMethod (true);
if (method == null)
method = property.GetGetMethod (true);
string visibility = GetMethodVisibility(method);
if (visibility == null)
return null;
string modifiers = String.Empty;
if (method.IsStatic) modifiers += " static";
if (method.IsVirtual) {
if ((method.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual";
else modifiers += " override";
}
if (method.IsAbstract) modifiers += " abstract";
if (method.IsFinal) modifiers += " sealed";
string name = property.Name;
string type_name = property.PropertyType.FullName;
type_name = ConvertCTSName (type_name);
string parameters = GetMethodParameters (property.GetIndexParameters());
if (parameters != "") parameters = "[" + parameters + "]";
string accessors = null;
if (property.CanRead && property.CanWrite)
accessors = "{ set; get; }";
else if (property.CanRead)
accessors = "{ get; }";
else if (property.CanWrite)
accessors = "{ set; }";
return String.Format ("{0}{1} {2} {3}{4} {5}",
visibility, modifiers, type_name, name, parameters, accessors);
}
static string MakeEventSignature (EventInfo ev) {
MethodInfo add = ev.GetAddMethod ();
string visibility = GetMethodVisibility(add);
if (visibility == null)
return null;
string modifiers = String.Empty;
if (add.IsStatic) modifiers += " static";
if (add.IsVirtual) {
if ((add.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual";
else modifiers += " override";
}
if (add.IsAbstract) modifiers += " abstract";
if (add.IsFinal) modifiers += " sealed";
string name = ev.Name;
string type = ConvertCTSName(ev.EventHandlerType.FullName);
return String.Format ("{0}{1} event {2} {3}",
visibility, modifiers, type, name);
}
static string MakeMemberSignature(MemberInfo mi) {
if (mi is ConstructorInfo) return MakeConstructorSignature((ConstructorInfo)mi);
if (mi is MethodInfo) return MakeMethodSignature((MethodInfo)mi);
if (mi is PropertyInfo) return MakePropertySignature((PropertyInfo)mi);
if (mi is FieldInfo) return MakeFieldSignature((FieldInfo)mi);
if (mi is EventInfo) return MakeEventSignature((EventInfo)mi);
throw new ArgumentException(mi.ToString());
}
static string GetMemberType(MemberInfo mi) {
if (mi is ConstructorInfo) return "Constructor";
if (mi is MethodInfo) return "Method";
if (mi is PropertyInfo) return "Property";
if (mi is FieldInfo) return "Field";
if (mi is EventInfo) return "Event";
throw new ArgumentException();
}
static string ConvertCTSName (string type, bool shorten)
{
if (shorten)
type = type.Substring (0, type.Length - 1);
string retval = ConvertCTSName (type);
return retval;
}
//
// Utility function: converts a fully .NET qualified type name into a C#-looking one
//
static string ConvertCTSName (string type) {
if (type.EndsWith ("[]"))
return ConvertCTSName(type.Substring(0, type.Length - 2).TrimEnd()) + "[]";
if (type.EndsWith ("&"))
return ConvertCTSName(type.Substring(0, type.Length - 1).TrimEnd()) + "&";
if (type.EndsWith ("*"))
return ConvertCTSName(type.Substring(0, type.Length - 1).TrimEnd()) + "*";
if (!type.StartsWith ("System."))
return type;
switch (type) {
case "System.Byte": return "byte";
case "System.SByte": return "sbyte";
case "System.Int16": return "short";
case "System.Int32": return "int";
case "System.Int64": return "long";
case "System.UInt16": return "ushort";
case "System.UInt32": return "uint";
case "System.UInt64": return "ulong";
case "System.Single": return "float";
case "System.Double": return "double";
case "System.Decimal": return "decimal";
case "System.Boolean": return "bool";
case "System.Char": return "char";
case "System.Void": return "void";
case "System.String": return "string";
case "System.Object": return "object";
}
return type;
}
}
--------------090302010809020706000207--