2 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
\r
3 Permission is hereby granted, free of charge, to any person obtaining a copy
\r
4 of this software and associated documentation files (the "Software"), to deal
\r
5 in the Software without restriction, including without limitation the rights
\r
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
7 copies of the Software, and to permit persons to whom the Software is
\r
8 furnished to do so, subject to the following conditions:
\r
10 The above copyright notice and this permission notice shall be included in
\r
11 all copies or substantial portions of the Software.
\r
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
23 // Author: Antonio Cisternino
\r
25 // Last update: 5/12/2001
\r
26 // Modified Jan 2004 by kokholm@itu.dk
\r
30 using System.Reflection;
\r
33 using System.Diagnostics;
\r
39 private Assembly assembly;
\r
41 //private XmlDocument xml;
\r
43 private string defaultNamespace;
\r
45 private string assemblyName;
\r
47 private static C5.HashDictionary<string, string> longtype2short;
\r
49 private static C5.HashDictionary<string, XmlNode> cachedDocComments;
\r
53 longtype2short = new C5.HashDictionary<string, string>();
\r
54 cachedDocComments = new C5.HashDictionary<string, XmlNode>();
\r
55 longtype2short.Add("System.Boolean", "bool");
\r
56 longtype2short.Add("System.Byte", "byte");
\r
57 longtype2short.Add("System.Int32", "int");
\r
58 longtype2short.Add("System.Double", "double");
\r
59 longtype2short.Add("System.Void", "void");
\r
60 longtype2short.Add("System.Object", "object");
\r
61 longtype2short.Add("System.String", "string");
\r
62 longtype2short.Add("System.Collections.Generic.IEnumerable{T}", "IEnumerable{T}");
\r
63 longtype2short.Add("System.Collections.Generic.IEnumerable{U}", "IEnumerable{U}");
\r
64 //longtype2short.Add("", "");
\r
68 DocNet(string a, string x, string defaultNamespace)
\r
70 this.defaultNamespace = defaultNamespace;
\r
71 assembly = Assembly.LoadFrom(a, null);
\r
72 XmlDocument xml = new XmlDocument();
\r
74 assemblyName = xml.SelectSingleNode("doc/assembly/name").InnerXml;
\r
76 if (!assembly.FullName.StartsWith(assemblyName + ","))
\r
77 throw new Exception("Wrong assembly specified!\n>> " + assembly.FullName + "\n>> " + assemblyName);
\r
79 foreach (XmlNode node in xml.SelectNodes("doc/members/member"))
\r
80 cachedDocComments.Add(node.SelectNodes("@name").Item(0).Value, node);
\r
84 private void CopyCodeDoc(XmlElement p, string xpath, XmlDocument ret)
\r
87 //xml.SelectSingleNode(xpath);
\r
89 if (cachedDocComments.Find(xpath, out n))
\r
91 foreach (XmlNode child in n.ChildNodes)
\r
92 p.AppendChild(ret.ImportNode(child, true));
\r
95 // Console.Error.WriteLine("docNet: {0} not found", xpath);
\r
98 string xmlClean(string s)
\r
100 // return s.Replace("&", "&").Replace("{", "<").Replace("}", ">").Replace("<", "<").Replace(">", ">");
\r
101 return s.Replace("{", "<").Replace("}", ">");
\r
104 private void AddSignature(XmlElement p, string signtext, XmlDocument ret)
\r
106 XmlElement sign = CreateElement(ret, "Signature");
\r
110 sign.InnerXml = signtext.Replace("&", "&").Replace("{", "<").Replace("}", ">").Replace("<", "<").Replace(">", ">");
\r
112 catch (XmlException)
\r
114 Console.Error.WriteLine(signtext);
\r
116 p.AppendChild(sign);
\r
119 private void addImplements(XmlElement p, Type t, XmlDocument ret)
\r
121 foreach (Type ty in t.GetInterfaces())
\r
123 XmlElement impl = CreateElement(ret, "Implements");
\r
125 if (ty.Assembly == assembly)
\r
127 impl.SetAttribute("refid", "T:" + canonicalTypeName(ty, null));
\r
128 impl.SetAttribute("C5", "");
\r
130 AddSignature(impl, prettyTypeName(ty), ret);
\r
131 p.AppendChild(impl);
\r
135 private void addBases(XmlElement p, Type t, XmlDocument ret)
\r
137 Type ty = t.BaseType;
\r
141 XmlElement @base = CreateElement(ret, "Bases");
\r
143 if (ty.Assembly == assembly)
\r
145 @base.SetAttribute("refid", "T:" + canonicalTypeName(ty, null));
\r
146 @base.SetAttribute("C5", "");
\r
149 AddSignature(@base, prettyTypeName(ty), ret);
\r
150 p.PrependChild(@base);
\r
157 private XmlElement CreateElement(XmlDocument ret, string name)
\r
159 return ret.CreateElement(null, name, null);
\r
162 private void VisitField(bool inherited, FieldInfo f, XmlElement type, XmlDocument refman)
\r
164 if (f.Name.Equals("value__"))
\r
166 string refid = "F:" + canonicalTypeName(f.DeclaringType, null) + "." + f.Name;
\r
167 //string xpath = "doc/members/member[@name = \"" + refid + "\"]";
\r
168 XmlElement el = CreateElement(refman, "Field");
\r
170 el.SetAttribute("Name", f.Name);
\r
171 el.SetAttribute("refid", refid);
\r
172 el.SetAttribute("Static", f.IsStatic.ToString());
\r
173 el.SetAttribute("Declared", xmlClean(prettyTypeName(f.DeclaringType)));
\r
174 el.SetAttribute("CDeclared", canonicalTypeName(f.DeclaringType, null));
\r
175 el.SetAttribute("Type", xmlClean(prettyTypeName(f.FieldType)));
\r
176 el.SetAttribute("Access", f.IsPublic ? "public" : (f.IsPrivate || f.IsAssembly ? "private" : "protected"));
\r
177 if (f.DeclaringType.Assembly == assembly)
\r
178 el.SetAttribute("C5", "");
\r
181 el.SetAttribute("Inherited", "");
\r
183 AddSignature(el, /*prettyTypeName(f.FieldType) + " " +*/ f.Name, refman);
\r
184 CopyCodeDoc(el, refid, refman);
\r
185 //AddSummary(el, xpath + "/summary", ret, doc);
\r
186 type.AppendChild(el);
\r
189 private void VisitEvent(bool inherited, EventInfo e, XmlElement type, XmlDocument ret)
\r
191 string refid = "E:" + canonicalTypeName(e.DeclaringType, null) + "." + e.Name;
\r
192 //string xpath = "doc/members/member[@name = \"" + refid + "\"]";
\r
193 XmlElement el = CreateElement(ret, "Event");
\r
195 el.SetAttribute("Name", e.Name);
\r
196 el.SetAttribute("refid", refid);
\r
197 //el.SetAttribute("Static", f.IsStatic.ToString());
\r
198 //TODO: check virtual and final values on adders/removers
\r
199 //el.SetAttribute("Virtual", e..IsVirtual.ToString());
\r
200 //el.SetAttribute("Final", e.IsFinal.ToString());
\r
201 el.SetAttribute("Declared", xmlClean(prettyTypeName(e.DeclaringType)));
\r
202 el.SetAttribute("CDeclared", canonicalTypeName(e.DeclaringType, null));
\r
203 el.SetAttribute("Type", xmlClean(prettyTypeName(e.EventHandlerType)));
\r
204 MethodInfo addMethod = e.GetAddMethod(true);
\r
205 el.SetAttribute("Access", addMethod.IsPublic ? "public" : addMethod.IsFamily ? "protected" : "private");//NBNBNB! e.IsPublic ? "public" : (e.IsPrivate || e.IsAssembly ? "private" : "protected"));
\r
206 if (e.DeclaringType.Assembly == assembly)
\r
207 el.SetAttribute("C5", "");
\r
210 el.SetAttribute("Inherited", "");
\r
212 AddSignature(el, /*prettyTypeName(e.EventHandlerType) + " " +*/ e.Name, ret);
\r
213 CopyCodeDoc(el, refid, ret);
\r
214 //AddSummary(el, xpath + "/summary", ret, doc);
\r
215 type.AppendChild(el);
\r
219 private void VisitProperty(bool inherited, PropertyInfo p, XmlElement type, XmlDocument ret)
\r
221 string refid = "P:" + canonicalPropertyName(p);
\r
222 string xpath = "doc/members/member[@name = \"" + refid + "\"]";
\r
223 XmlElement el = CreateElement(ret, "Property");
\r
225 el.SetAttribute("Name", p.Name);
\r
226 el.SetAttribute("refid", refid);
\r
227 el.SetAttribute("Access", "public");//TODO: check if reasonable
\r
228 MethodInfo m = p.CanRead ? p.GetGetMethod() : p.GetSetMethod();
\r
231 el.SetAttribute("Static", m.IsStatic.ToString());
\r
232 el.SetAttribute("Abstract", m.IsAbstract.ToString());
\r
233 el.SetAttribute("Virtual", m.IsVirtual.ToString());
\r
234 el.SetAttribute("Final", m.IsFinal.ToString());
\r
237 //Console.Error.WriteLine("%%%%% {0} | {1}", p, p.DeclaringType);
\r
238 el.SetAttribute("Declared", xmlClean(prettyTypeName(p.DeclaringType)));
\r
239 el.SetAttribute("CDeclared", canonicalTypeName(p.DeclaringType, null));
\r
240 el.SetAttribute("Get", p.CanRead.ToString());
\r
241 el.SetAttribute("Set", p.CanWrite.ToString());
\r
242 el.SetAttribute("Type", xmlClean(prettyTypeName(p.PropertyType)));
\r
244 if (p.DeclaringType.Assembly == assembly)
\r
245 el.SetAttribute("C5", "");
\r
248 el.SetAttribute("Inherited", "");
\r
250 if (p.Name.Equals("Item"))
\r
251 AddSignature(el, prettyIndexerSignature(p), ret);
\r
253 AddSignature(el, /*prettyTypeName(p.PropertyType) + " " +*/ p.Name, ret);
\r
255 //AddSummary(el, xpath + "/summary", ret, doc);
\r
256 CopyCodeDoc(el, refid, ret);
\r
257 //AddValue(el, xpath + "/value", ret, doc);
\r
258 VisitParameters(p.GetIndexParameters(), el, ret, xpath);
\r
259 type.AppendChild(el);
\r
263 private void VisitParameters(ParameterInfo[] pars, XmlElement n, XmlDocument ret, string xpath)
\r
265 foreach (ParameterInfo p in pars)
\r
267 XmlElement el = CreateElement(ret, "Parameter");
\r
269 el.SetAttribute("Name", p.Name);
\r
270 el.SetAttribute("Type", prettyTypeName(p.ParameterType));
\r
271 //AddSummary(el, xpath + "/param[@name = \"" + p.Name + "\"]", ret, doc);
\r
272 CopyCodeDoc(el, xpath + "/param[@name = \"" + p.Name + "\"]", ret);
\r
279 private void VisitConstructor(Type t, ConstructorInfo c, XmlElement type, XmlDocument ret)
\r
281 Type declaringType = c.DeclaringType;
\r
282 string refid = "M:" + canonicalTypeName(c.DeclaringType, null) + "." + "#ctor";
\r
284 refid += canonicalParameters(c.GetParameters(), new string[]{});
\r
286 string xpath = "doc/members/member[@name = \"" + refid + "\"]";
\r
287 XmlElement el = CreateElement(ret, "Constructor");
\r
288 el.SetAttribute("Foo", c.IsConstructor ? "Con" : "San");
\r
289 el.SetAttribute("refid", refid);
\r
290 el.SetAttribute("Declared", prettyTypeName(declaringType));
\r
291 el.SetAttribute("CDeclared", canonicalTypeName(declaringType, null));
\r
292 el.SetAttribute("Access", c.IsPublic ? "public" : (c.IsPrivate ? "private" : "protected"));
\r
293 //el.SetAttribute("Access", c.IsPublic ? "public" : (c.IsPrivate || c.IsAssembly ? "private" : "protected"));
\r
294 if (declaringType.Assembly == assembly)
\r
295 el.SetAttribute("C5", "");
\r
296 if (declaringType != t)
\r
297 el.SetAttribute("Inherited", "");
\r
298 AddSignature(el, prettyConstructorSignature(c), ret);
\r
299 CopyCodeDoc(el, refid, ret);
\r
300 //AddSummary(el, xpath + "/summary", ret, doc);
\r
301 VisitParameters(c.GetParameters(), el, ret, xpath);
\r
302 type.AppendChild(el);
\r
306 private void VisitMethod(bool inherited, MethodInfo m, XmlElement type, XmlDocument ret)
\r
308 if (m.Name.StartsWith("get_") || m.Name.StartsWith("set_") || m.Name.StartsWith("add_") || m.Name.StartsWith("remove_"))
\r
310 bool isOperator = m.Name.StartsWith("op_");
\r
312 string refid = "M:" + canonicalMethodName(m);
\r
314 string xpath = "doc/members/member[@name = \"" + refid + "\"]";
\r
315 XmlElement el = CreateElement(ret, isOperator ? "Operator" : "Method");
\r
317 string mangledName = m.Name;
\r
320 switch (mangledName)
\r
322 case "op_Equality": mangledName = "operator =="; break;
\r
323 case "op_Inequality": mangledName = "operator !="; break;
\r
324 default: throw new ApplicationException("unknown operatorname, " + mangledName);
\r
327 el.SetAttribute("Name", mangledName);
\r
328 el.SetAttribute("refid", refid);
\r
329 el.SetAttribute("Static", m.IsStatic.ToString());
\r
330 el.SetAttribute("Abstract", m.IsAbstract.ToString());
\r
331 el.SetAttribute("Virtual", m.IsVirtual.ToString());
\r
332 el.SetAttribute("Final", m.IsFinal.ToString());
\r
333 el.SetAttribute("Declared", xmlClean(prettyTypeName(m.DeclaringType)));
\r
334 el.SetAttribute("CDeclared", canonicalTypeName(m.DeclaringType, null));
\r
335 el.SetAttribute("ReturnType", xmlClean(prettyTypeName(m.ReturnType)));
\r
336 if (m.DeclaringType.Assembly == assembly)
\r
337 el.SetAttribute("C5", "");
\r
339 el.SetAttribute("Inherited", "");
\r
340 el.SetAttribute("Access", m.IsPublic ? "public" : (m.IsPrivate || m.IsAssembly ? "private" : "protected"));
\r
341 el.SetAttribute("Sealed", m.IsFinal.ToString());
\r
342 AddSignature(el, prettyMethodSignature(mangledName, m), ret);
\r
343 CopyCodeDoc(el, refid, ret);
\r
344 VisitParameters(m.GetParameters(), el, ret, xpath);
\r
346 foreach (Type gp in m.GetGenericArguments())
\r
347 foreach (Type gc in gp.GetGenericParameterConstraints())
\r
348 if (gc != typeof(object))
\r
350 XmlElement constraint = CreateElement(ret, "constraint");
\r
351 constraint.SetAttribute("Value", prettyTypeName(gp) + " : " + xmlClean(prettyTypeName(gc)));
\r
352 el.AppendChild(constraint);
\r
354 type.AppendChild(el);
\r
357 public XmlDocument GenerateDoc()
\r
359 BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;
\r
361 XmlDocument ret = new XmlDocument();
\r
362 XmlElement root = CreateElement(ret, "Assembly");
\r
364 root.SetAttribute("Name", assemblyName);
\r
366 ret.AppendChild(root);
\r
368 XmlElement type = null;
\r
369 //string xpath = null;
\r
371 foreach (Type t in assembly.GetTypes())
\r
373 if (t.Name.StartsWith("DocNet"))
\r
378 type = CreateElement(ret, "Interface");
\r
379 foreach (EventInfo e in t.GetEvents(flags))
\r
380 VisitEvent(e.DeclaringType != t, e, type, ret);
\r
382 foreach (PropertyInfo p in t.GetProperties(flags))
\r
383 VisitProperty(false, p, type, ret);
\r
385 foreach (MethodInfo m in t.GetMethods(flags))
\r
386 VisitMethod(false, m, type, ret);
\r
388 else if (t.IsValueType)
\r
390 type = CreateElement(ret, "Struct");
\r
391 foreach (FieldInfo f in t.GetFields(flags))
\r
392 VisitField(f.DeclaringType != t, f, type, ret);
\r
394 foreach (EventInfo e in t.GetEvents(flags))
\r
395 VisitEvent(e.DeclaringType != t, e, type, ret);
\r
397 foreach (PropertyInfo p in t.GetProperties(flags))
\r
398 VisitProperty(p.DeclaringType != t, p, type, ret);
\r
400 foreach (ConstructorInfo c in t.GetConstructors(flags))
\r
401 VisitConstructor(t, c, type, ret);
\r
403 foreach (MethodInfo m in t.GetMethods(flags))
\r
404 VisitMethod(m.DeclaringType != t, m, type, ret);
\r
406 else if (t.IsSubclassOf(typeof(Delegate)))
\r
408 type = CreateElement(ret, "Delegate");
\r
409 VisitMethod(false, t.GetMethod("Invoke"), type, ret);
\r
413 type = CreateElement(ret, "Class");
\r
414 foreach (FieldInfo f in t.GetFields(flags))
\r
415 VisitField(f.DeclaringType != t, f, type, ret);
\r
417 foreach (EventInfo e in t.GetEvents(flags))
\r
418 VisitEvent(e.DeclaringType != t, e, type, ret);
\r
420 foreach (PropertyInfo p in t.GetProperties(flags))
\r
421 VisitProperty(p.DeclaringType != t, p, type, ret);
\r
423 foreach (ConstructorInfo c in t.GetConstructors(flags))
\r
424 VisitConstructor(t, c, type, ret);
\r
426 foreach (MethodInfo m in t.GetMethods(flags))
\r
427 VisitMethod(m.DeclaringType != t, m, type, ret);
\r
430 type.SetAttribute("Name", xmlClean(prettyTypeName(t)));
\r
431 type.SetAttribute("Access", t.IsPublic || t.IsNestedPublic ? "public" : t.IsNestedFamily ? "protected" : "private");
\r
433 string refid = "T:" + canonicalTypeName(t, null);
\r
435 type.SetAttribute("refid", refid);
\r
436 type.SetAttribute("C5", "");
\r
437 AddSignature(type, prettyTypeName(t), ret);
\r
438 addImplements(type, t, ret);
\r
439 addBases(type, t, ret);
\r
441 foreach (Type gp in t.GetGenericArguments())
\r
443 if (gp.GenericParameterAttributes != GenericParameterAttributes.None)
\r
445 XmlElement constraint = CreateElement(ret, "constraint");
\r
446 string constraintText = null;
\r
447 switch (gp.GenericParameterAttributes)
\r
449 case GenericParameterAttributes.Contravariant:
\r
451 case GenericParameterAttributes.Covariant:
\r
453 case GenericParameterAttributes.DefaultConstructorConstraint:
\r
454 constraintText = "new()";
\r
456 case GenericParameterAttributes.None:
\r
458 case GenericParameterAttributes.ReferenceTypeConstraint:
\r
459 constraintText = "class";
\r
461 case GenericParameterAttributes.SpecialConstraintMask:
\r
463 case GenericParameterAttributes.NotNullableValueTypeConstraint:
\r
464 constraintText = "struct";
\r
466 case GenericParameterAttributes.VarianceMask:
\r
469 constraint.SetAttribute("Value", String.Format("{0} : {1}", gp, constraintText));
\r
470 type.AppendChild(constraint);
\r
472 foreach (Type gc in gp.GetGenericParameterConstraints())
\r
474 if (gc != typeof(object))
\r
476 XmlElement constraint = CreateElement(ret, "constraint");
\r
477 constraint.SetAttribute("Value", String.Format("{0} : {1}", prettyTypeName(gp), xmlClean(prettyTypeName(gc))));
\r
478 type.AppendChild(constraint);
\r
483 CopyCodeDoc(type, refid, ret);
\r
484 root.AppendChild(type);
\r
490 C5.HashDictionary<Type, string> t2ptn = new C5.HashDictionary<Type, string>();
\r
491 private string prettyTypeName(Type t)
\r
494 //if (!t2ptn.Find(t, out retval))
\r
497 retval = prettyTypeName(t, ref consumed);
\r
498 // t2ptn.Add(t, retval);
\r
503 private string prettyTypeName(Type t, ref int consumed)
\r
505 StringBuilder ret = new StringBuilder();
\r
507 if (t.IsGenericParameter)
\r
508 ret.Append(t.Name);
\r
509 else if (t.IsArray)
\r
510 ret.Append(prettyTypeName(t.GetElementType()) + "[]");
\r
511 else if (t.IsByRef)
\r
512 ret.Append("ref ").Append(prettyTypeName(t.GetElementType()));
\r
513 else if (!t.IsGenericType)
\r
514 ret.Append(t.IsNested ? prettyTypeName(t.DeclaringType, ref consumed) + "." + t.Name : t.FullName);
\r
518 StringBuilder gps = new StringBuilder();
\r
519 Type[] gp = t.GetGenericArguments();
\r
521 ret.Append(t.IsNested ? prettyTypeName(t.DeclaringType, ref consumed) : t.Namespace).Append(".").Append(t.Name);
\r
522 if (consumed < gp.Length)
\r
524 //TODO: fix this ugly hack to remove `n
\r
525 ret.Remove(ret.Length - 2, 2);
\r
526 //ret = ret.Substring(0, ret.Length - 2);
\r
527 for (int i = consumed, length = gp.Length; i < length; i++)
\r
531 if (first) first = false;
\r
535 gps.Append(prettyTypeName(ty));
\r
538 consumed = gp.Length;
\r
539 ret.Append("{").Append(gps.ToString()).Append("}");
\r
543 string retval = ret.ToString();
\r
545 if (retval.StartsWith(defaultNamespace + "."))
\r
546 retval = retval.Substring(defaultNamespace.Length + 1);
\r
548 if (longtype2short.Contains(retval))
\r
549 retval = longtype2short[retval];
\r
554 private string prettyParameters(ParameterInfo[] pars)
\r
559 foreach (ParameterInfo p in pars)
\r
561 if (first) first = false;
\r
564 Type pt = p.ParameterType;
\r
568 pt = pt.GetElementType();
\r
571 ret += prettyTypeName(pt) + " " + p.Name;
\r
577 private string prettyMethodSignature(string name, MethodInfo m)
\r
580 if (m.IsGenericMethod)
\r
582 Type[] gps = m.GetGenericArguments();
\r
585 for (int i = 0; i < gps.Length; i++)
\r
586 gp += (i == 0 ? "" : ",") + gps[i].Name;
\r
591 return name + gp + "(" + prettyParameters(m.GetParameters()) + ")";
\r
594 private string prettyConstructorSignature(ConstructorInfo c)
\r
596 Type t = c.DeclaringType;
\r
598 return prettyTypeName(t) + "(" + prettyParameters(c.GetParameters()) + ")";
\r
601 private string prettyIndexerSignature(PropertyInfo p)
\r
603 return /*prettyTypeName(p.PropertyType) + " " + */ "this[" + prettyParameters(p.GetIndexParameters()) + "]";
\r
607 private string simpleTypeName(Type t)
\r
609 return (t.IsNested ? simpleTypeName(t.DeclaringType) : t.Namespace) + "." + t.Name;
\r
613 private string canonicalTypeName(Type t, string[] mgps)
\r
617 if (t.IsGenericParameter)
\r
618 ret = "`" + t.GenericParameterPosition;
\r
619 else if (t.IsArray)
\r
620 ret = canonicalTypeName(t.GetElementType(), mgps) + "[]";
\r
621 else if (t.IsByRef)
\r
622 ret = canonicalTypeName(t.GetElementType(), mgps) + "@";
\r
625 ret = simpleTypeName(t);
\r
626 if (!t.IsGenericType)
\r
628 else if (mgps == null)
\r
629 ret += "";//"`" + t.GetGenericArguments().Length;
\r
632 //TODO: fix this ugly hack to remove `n
\r
633 ret = ret.Substring(0, ret.Length - 2);
\r
637 Type[] gp = t.GetGenericArguments();
\r
639 foreach (Type ty in gp)
\r
641 if (first) first = false;
\r
645 if (ty.IsGenericParameter)
\r
647 bool ismgp = false;
\r
649 foreach (string s in mgps) if (s.Equals(ty.Name)) ismgp = true;
\r
651 gps += (ismgp ? "``" : "`") + ty.GenericParameterPosition;
\r
654 gps += canonicalTypeName(ty, mgps);
\r
657 ret += "{" + gps + "}";
\r
664 private string canonicalMethodName(MethodInfo m)
\r
666 string ret = canonicalTypeName(m.DeclaringType, null) + "." + m.Name;
\r
670 if (m.IsGenericMethod)
\r
672 Type[] gps = m.GetGenericArguments();
\r
674 ret += "``" + gps.Length;
\r
675 gmps = new string[gps.Length];
\r
676 for (int i = 0; i < gps.Length; i++)
\r
677 gmps[i] = gps[i].Name;
\r
680 gmps = new string[]{};
\r
682 ret += canonicalParameters(m.GetParameters(), gmps);
\r
686 private string canonicalPropertyName(PropertyInfo p)
\r
688 string pname = canonicalTypeName(p.DeclaringType, null) + "." + p.Name;
\r
689 ParameterInfo[] pars = p.GetIndexParameters();
\r
691 if (pars.Length > 0)
\r
692 pname += canonicalParameters(pars, new string[]{});
\r
697 private string canonicalParameters(ParameterInfo[] pars, string[] gmps)
\r
699 if (pars.Length == 0) return "";
\r
704 foreach (ParameterInfo p in pars)
\r
706 if (first) first = false;
\r
710 ret += canonicalTypeName(p.ParameterType, gmps); ;
\r
713 return "(" + ret + ")";
\r
718 static void Main(string[] args)
\r
720 if (args.Length != 2)
\r
722 args = new string[] { @"C5.dll", @"C5.xml" };
\r
726 Timer timer = new Timer();
\r
728 DocNet doc = new DocNet(args[0], args[1], "C5");
\r
729 XmlDocument merged = doc.GenerateDoc();
\r
730 Console.Error.WriteLine("Time merge: {0} ms", timer.snap());
\r
732 System.Xml.Xsl.XslCompiledTransform overview = new System.Xml.Xsl.XslCompiledTransform();
\r
733 overview.Load(@"overview.xslt");
\r
734 overview.Transform(merged, new XmlTextWriter(new StreamWriter(@"docbuild\contents.htm")));
\r
735 Console.Error.WriteLine("Time, overview: {0} ms", timer.snap());
\r
737 StringBuilder megaDoc = new StringBuilder();
\r
738 using (XmlWriter writer = XmlWriter.Create(megaDoc))
\r
740 writer.WriteStartElement("hack");
\r
741 System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
\r
742 trans.Load(@"trans.xslt");
\r
743 trans.Transform(merged, writer);
\r
744 writer.WriteEndElement();
\r
747 Console.Error.WriteLine("Time trans: {0} ms", timer.snap());
\r
748 System.Xml.XPath.XPathDocument megaXml =
\r
749 new System.Xml.XPath.XPathDocument(XmlReader.Create(new StringReader(megaDoc.ToString())));
\r
750 System.Xml.XPath.XPathNodeIterator nodes = megaXml.CreateNavigator().Select("/hack/*");
\r
751 string docfn = null;
\r
752 foreach (System.Xml.XPath.XPathNavigator var in nodes)
\r
754 if (var.Name == "filestart")
\r
755 docfn = var.GetAttribute("name", "");
\r
756 if (var.Name == "html")
\r
758 Console.Error.Write(".");
\r
759 XmlWriter w = new XmlTextWriter(new StreamWriter(@"docbuild\types\" + docfn));
\r
760 var.WriteSubtree(w);
\r
764 Console.Error.WriteLine();
\r
765 Console.Error.WriteLine("Time split: {0} ms", timer.snap());
\r
767 Console.Write("? ");
\r