using System;
using System.Collections;
-#if !NET_1_0
using System.Collections.Generic;
-#endif
+using System.Collections.ObjectModel;
+using System.Diagnostics;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Text;
-using System.Reflection;
using System.Xml;
using System.Xml.XPath;
-#if NET_1_0
-using Mono.GetOptions;
-
-using MemberInfoEnumerable = System.Collections.IEnumerable;
-using MyXmlNodeList = System.Collections.ArrayList;
-using StringList = System.Collections.ArrayList;
-using StringToStringMap = System.Collections.Hashtable;
-using StringToXmlNodeMap = System.Collections.Hashtable;
-#else
+using Mono.Cecil;
using Mono.Options;
-using MemberInfoEnumerable = System.Collections.Generic.IEnumerable<System.Reflection.MemberInfo>;
using MyXmlNodeList = System.Collections.Generic.List<System.Xml.XmlNode>;
using StringList = System.Collections.Generic.List<string>;
using StringToStringMap = System.Collections.Generic.Dictionary<string, string>;
using StringToXmlNodeMap = System.Collections.Generic.Dictionary<string, System.Xml.XmlNode>;
-#endif
namespace Mono.Documentation {
-#pragma warning disable 0618
-class MDocUpdaterOptions
-#if NET_1_0
- : Options
-#endif
+class MDocUpdater : MDocCommand
{
-#if NET_1_0
- [Option("The root {directory} of an assembly's documentation files.")]
-#endif
- public string path = null;
-
-#if NET_1_0
- [Option("When updating documentation, write the updated files to this {path}.")]
-#endif
- public string updateto = null;
-
-#if NET_1_0
- [Option(-1, "The assembly to document. Specify a {file} path or the name of a GAC'd assembly.")]
-#endif
- public string[] assembly = null;
-
-#if NET_1_0
- [Option(-1, "Document only the {type name}d by this argument.")]
-#endif
- public string[] type = null;
-
-#if NET_1_0
- [Option("Update only the types in this {namespace}.")]
-#endif
- public string @namespace = null;
-
-#if NET_1_0
- [Option("Allow monodocer to delete members from files.")]
-#endif
- public bool delete = false;
-
-#if NET_1_0
- [Option("Include overridden methods in documentation.")]
-#endif
- public bool overrides = true;
-
-#if NET_1_0
- [Option("Don't update members.")]
-#endif
- public bool ignoremembers = false;
-
-#if NET_1_0
- [Option("Don't rename documentation XML files for missing types. IGNORED.")]
-#endif
- public bool ignore_extra_docs = false;
-
-#if NET_1_0
- [Option("The {name} of the project this documentation is for.")]
-#endif
- public string name;
-
-#if NET_1_0
- [Option("An XML documentation {file} made by the /doc option of mcs/csc the contents of which will be imported.")]
- public string importslashdoc;
+ string srcPath;
+ List<AssemblyDefinition> assemblies;
+ readonly DefaultAssemblyResolver assemblyResolver = new DefaultAssemblyResolver();
- [Option("An ECMA or monodoc-generated XML documemntation {file} to import.")]
- public string importecmadoc;
-#endif
+ bool delete;
+ bool show_exceptions;
+ bool no_assembly_versions, ignore_missing_types;
+ ExceptionLocations? exceptions;
+
+ internal int additions = 0, deletions = 0;
-#if NET_1_0
- [Option("Import either a /doc or ECMA documentation file.")]
-#endif
- public string import;
+ List<DocumentationImporter> importers = new List<DocumentationImporter> ();
-#if NET_1_0
- [Option("Indent the XML files nicely.")]
-#endif
- public bool pretty = true;
-
-#if NET_1_0
- [Option("Create a <since/> element for added types/members with the value {since}.")]
-#endif
- public string since;
+ DocumentationEnumerator docEnum;
-#if NET_1_0
- [Option("Show full stack trace on error.")]
-#endif
- public bool show_exceptions;
-}
-#pragma warning restore
+ string since;
-class MDocUpdater
-#if !NET_1_0
- : MDocCommand
-#endif
-{
-
- static string srcPath;
- static Assembly[] assemblies;
-
- static bool nooverrides = true, delete = false, ignoremembers = false;
- static bool pretty = false;
- static bool show_exceptions = false;
-
- static int additions = 0, deletions = 0;
+ static readonly MemberFormatter docTypeFormatter = new DocTypeMemberFormatter ();
+ static readonly MemberFormatter filenameFormatter = new FileNameMemberFormatter ();
- static string name;
- static XmlDocument slashdocs;
- static XmlReader ecmadocs;
+ static MemberFormatter[] typeFormatters = new MemberFormatter[]{
+ new CSharpMemberFormatter (),
+ new ILMemberFormatter (),
+ };
- static string since;
+ static MemberFormatter[] memberFormatters = new MemberFormatter[]{
+ new CSharpFullMemberFormatter (),
+ new ILFullMemberFormatter (),
+ };
- static MemberFormatter csharpFullFormatter = new CSharpFullMemberFormatter ();
- static MemberFormatter csharpFormatter = new CSharpMemberFormatter ();
- static MemberFormatter docTypeFormatter = new DocTypeMemberFormatter ();
- static MemberFormatter slashdocFormatter = new SlashDocMemberFormatter ();
- static MemberFormatter filenameFormatter = new FileNameMemberFormatter ();
+ internal static readonly MemberFormatter slashdocFormatter = new SlashDocMemberFormatter ();
- static MyXmlNodeList extensionMethods = new MyXmlNodeList ();
+ MyXmlNodeList extensionMethods = new MyXmlNodeList ();
- const BindingFlags DefaultBindingFlags =
- BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
-
-#if NET_1_0
- public static void Main(string[] args)
- {
- MDocUpdaterOptions opts = new MDocUpdaterOptions ();
- opts.ProcessArgs(args);
+ HashSet<string> forwardedTypes = new HashSet<string> ();
- if (args.Length == 0) {
- opts.DoHelp();
- return;
- }
- Run (opts);
- }
-#else
public override void Run (IEnumerable<string> args)
{
- var opts = new MDocUpdaterOptions {
- overrides = true,
- pretty = true,
- show_exceptions = DebugOutput,
- };
-
- var types = new List<string> ();
+ show_exceptions = DebugOutput;
+ var types = new List<string> ();
var p = new OptionSet () {
- { "o|out=",
- "Root {DIRECTORY} to generate/update documentation.",
- v => opts.path = v },
- { "i|import=",
- "Import documentation from {FILE}.",
- v => opts.import = v },
{ "delete",
"Delete removed members from the XML files.",
- v => opts.delete = v != null },
+ v => delete = v != null },
+ { "exceptions:",
+ "Document potential exceptions that members can generate. {SOURCES} " +
+ "is a comma-separated list of:\n" +
+ " asm Method calls in same assembly\n" +
+ " depasm Method calls in dependent assemblies\n" +
+ " all Record all possible exceptions\n" +
+ " added Modifier; only create <exception/>s\n" +
+ " for NEW types/members\n" +
+ "If nothing is specified, then only exceptions from the member will " +
+ "be listed.",
+ v => exceptions = ParseExceptionLocations (v) },
+ { "f=",
+ "Specify a {FLAG} to alter behavior. See later -f* options for available flags.",
+ v => {
+ switch (v) {
+ case "ignore-missing-types":
+ ignore_missing_types = true;
+ break;
+ case "no-assembly-versions":
+ no_assembly_versions = true;
+ break;
+ default:
+ throw new Exception ("Unsupported flag `" + v + "'.");
+ }
+ } },
+ { "fignore-missing-types",
+ "Do not report an error if a --type=TYPE type\nwas not found.",
+ v => ignore_missing_types = v != null },
+ { "fno-assembly-versions",
+ "Do not generate //AssemblyVersion elements.",
+ v => no_assembly_versions = v != null },
+ { "i|import=",
+ "Import documentation from {FILE}.",
+ v => AddImporter (v) },
+ { "L|lib=",
+ "Check for assembly references in {DIRECTORY}.",
+ v => assemblyResolver.AddSearchDirectory (v) },
+ { "library=",
+ "Ignored for compatibility with update-ecma-xml.",
+ v => {} },
+ { "o|out=",
+ "Root {DIRECTORY} to generate/update documentation.",
+ v => srcPath = v },
+ { "r=",
+ "Search for dependent assemblies in the directory containing {ASSEMBLY}.\n" +
+ "(Equivalent to '-L `dirname ASSEMBLY`'.)",
+ v => assemblyResolver.AddSearchDirectory (Path.GetDirectoryName (v)) },
{ "since=",
- "Manually specify the assembly version that new members were added in.",
- v => opts.since = v },
+ "Manually specify the assembly {VERSION} that new members were added in.",
+ v => since = v },
{ "type=",
"Only update documentation for {TYPE}.",
v => types.Add (v) },
};
- List<string> extra = Parse (p, args, "update",
+ var assemblies = Parse (p, args, "update",
"[OPTIONS]+ ASSEMBLIES",
"Create or update documentation from ASSEMBLIES.");
- if (extra == null)
+ if (assemblies == null)
return;
- if (extra.Count == 0)
+ if (assemblies.Count == 0)
Error ("No assemblies specified.");
- opts.assembly = extra.ToArray ();
- if (types.Count > 0)
- opts.type = types.ToArray ();
- Run (opts);
- opts.name = ""; // remove warning about unused member
- }
-#endif
+ foreach (var dir in assemblies
+ .Where (a => a.Contains (Path.DirectorySeparatorChar))
+ .Select (a => Path.GetDirectoryName (a)))
+ assemblyResolver.AddSearchDirectory (dir);
+
+ // PARSE BASIC OPTIONS AND LOAD THE ASSEMBLY TO DOCUMENT
- public static void Run (MDocUpdaterOptions opts)
- {
- nooverrides = !opts.overrides;
- delete = opts.delete;
- ignoremembers = opts.ignoremembers;
- name = opts.name;
- pretty = opts.pretty;
- since = opts.since;
- show_exceptions = opts.show_exceptions;
+ if (srcPath == null)
+ throw new InvalidOperationException("The --out option is required.");
+
+ this.assemblies = assemblies.Select (a => LoadAssembly (a)).ToList ();
- try {
- // PARSE BASIC OPTIONS AND LOAD THE ASSEMBLY TO DOCUMENT
-
- if (opts.path == null)
- throw new InvalidOperationException("The path option is required.");
-
- srcPath = opts.path;
+ // Store types that have been forwarded to avoid duplicate generation
+ GatherForwardedTypes ();
- if (opts.type != null && opts.type.Length > 0 && opts.@namespace != null)
- throw new InvalidOperationException("You cannot specify both 'type' and 'namespace'.");
-
- if (opts.assembly == null)
- throw new InvalidOperationException("The assembly option is required.");
-
- assemblies = new Assembly [opts.assembly.Length];
- for (int i = 0; i < opts.assembly.Length; i++)
- assemblies [i] = LoadAssembly (opts.assembly [i]);
-
- // IMPORT FROM /DOC?
-
-#if NET_1_0
- if (opts.importslashdoc != null) {
- try {
- slashdocs = new XmlDocument();
- slashdocs.Load(opts.importslashdoc);
- } catch (Exception e) {
- Error ("Could not load /doc file: {0}", e.Message);
- Environment.ExitCode = 1;
- return;
- }
- }
-
- if (opts.importecmadoc != null) {
- try {
- ecmadocs = new XmlTextReader (opts.importecmadoc);
- } catch (Exception e) {
- Error ("Could not load ECMA XML file: {0}", e.Message);
- Environment.ExitCode = 1;
- return;
- }
- }
+ docEnum = docEnum ?? new DocumentationEnumerator ();
+
+ // PERFORM THE UPDATES
+
+ if (types.Count > 0) {
+ types.Sort ();
+ DoUpdateTypes (srcPath, types, srcPath);
+ }
+#if false
+ else if (opts.@namespace != null)
+ DoUpdateNS (opts.@namespace, Path.Combine (opts.path, opts.@namespace),
+ Path.Combine (dest_dir, opts.@namespace));
#endif
+ else
+ DoUpdateAssemblies (srcPath, srcPath);
- if (opts.import != null && ecmadocs == null && slashdocs == null) {
- try {
- XmlReader r = new XmlTextReader (opts.import);
- if (r.Read ()) {
- while (r.NodeType != XmlNodeType.Element) {
- if (!r.Read ())
- throw new Exception ("Unable to read XML file: " +
- opts.import);
- }
- if (r.LocalName == "doc") {
- slashdocs = new XmlDocument();
- slashdocs.Load (opts.import);
- }
- else if (r.LocalName == "Libraries") {
- ecmadocs = new XmlTextReader (opts.import);
- }
- else
- throw new Exception ("Unsupported XML format within " + opts.import);
- }
- r.Close ();
- } catch (Exception e) {
- Error ("Could not load XML file: {0}", e.Message);
- Environment.ExitCode = 1;
- return;
+ Console.WriteLine("Members Added: {0}, Members Deleted: {1}", additions, deletions);
+ }
+
+ void AddImporter (string path)
+ {
+ try {
+ XmlReader r = new XmlTextReader (path);
+ if (r.Read ()) {
+ while (r.NodeType != XmlNodeType.Element) {
+ if (!r.Read ())
+ Error ("Unable to read XML file: {0}.", path);
+ }
+ if (r.LocalName == "doc") {
+ importers.Add (new MsxdocDocumentationImporter (path));
}
+ else if (r.LocalName == "Libraries") {
+ var ecmadocs = new XmlTextReader (path);
+ docEnum = new EcmaDocumentationEnumerator (this, ecmadocs);
+ importers.Add (new EcmaDocumentationImporter (ecmadocs));
+ }
+ else
+ Error ("Unsupported XML format within {0}.", path);
}
-
- // PERFORM THE UPDATES
-
- string dest_dir = opts.updateto != null ? opts.updateto : opts.path;
- if (opts.type != null && opts.type.Length > 0)
- DoUpdateTypes(opts.path, opts.type, dest_dir);
- else if (opts.@namespace != null)
- DoUpdateNS (opts.@namespace, Path.Combine (opts.path, opts.@namespace),
- Path.Combine (dest_dir, opts.@namespace));
- else
- DoUpdateAssemblies(opts.path, dest_dir);
-
- } catch (InvalidOperationException error) {
- Error (opts.show_exceptions ? error.ToString () : error.Message);
- Environment.ExitCode = 1;
- return;
-
- } catch (System.IO.IOException error) {
- Error (opts.show_exceptions ? error.ToString () : error.Message);
- Environment.ExitCode = 1;
- return;
-
- } catch (Exception error) {
- Error (opts.show_exceptions ? error.ToString () : error.Message);
+ r.Close ();
+ } catch (Exception e) {
Environment.ExitCode = 1;
+ Error ("Could not load XML file: {0}.", e.Message);
}
+ }
- Console.WriteLine("Members Added: {0}, Members Deleted: {1}", additions, deletions);
+ void GatherForwardedTypes ()
+ {
+ foreach (var asm in assemblies)
+ foreach (var type in asm.MainModule.ExportedTypes.Where (t => t.IsForwarder).Select (t => t.FullName))
+ forwardedTypes.Add (type);
}
- private static
-#if !NET_1_0
- new
-#endif
- void Error (string format, params object[] args)
+ static ExceptionLocations ParseExceptionLocations (string s)
+ {
+ ExceptionLocations loc = ExceptionLocations.Member;
+ if (s == null)
+ return loc;
+ foreach (var type in s.Split (',')) {
+ switch (type) {
+ case "added": loc |= ExceptionLocations.AddedMembers; break;
+ case "all": loc |= ExceptionLocations.Assembly | ExceptionLocations.DependentAssemblies; break;
+ case "asm": loc |= ExceptionLocations.Assembly; break;
+ case "depasm": loc |= ExceptionLocations.DependentAssemblies; break;
+ default: throw new NotSupportedException ("Unsupported --exceptions value: " + type);
+ }
+ }
+ return loc;
+ }
+
+ internal void Warning (string format, params object[] args)
{
- Console.Error.Write ("monodocer: ");
- Console.Error.WriteLine (format, args);
+ Message (TraceLevel.Warning, "mdoc: " + format, args);
}
- private static Assembly LoadAssembly (string name)
+ private AssemblyDefinition LoadAssembly (string name)
{
- Assembly assembly = null;
+ AssemblyDefinition assembly = null;
try {
- assembly = Assembly.LoadFile (name);
+ assembly = AssemblyDefinition.ReadAssembly (name, new ReaderParameters { AssemblyResolver = assemblyResolver });
} catch (System.IO.FileNotFoundException) { }
- if (assembly == null) {
- try {
-#pragma warning disable 0612
- assembly = Assembly.LoadWithPartialName (name);
-#pragma warning restore
- } catch (Exception) { }
- }
-
if (assembly == null)
throw new InvalidOperationException("Assembly " + name + " not found.");
output.WriteLine();
}
+ private static void WriteFile (string filename, FileMode mode, Action<TextWriter> action)
+ {
+ Action<string> creator = file => {
+ using (var writer = OpenWrite (file, mode))
+ action (writer);
+ };
+
+ MdocFile.UpdateFile (filename, creator);
+ }
+
private static void OrderTypeAttributes (XmlElement e)
{
foreach (XmlElement type in e.SelectNodes ("//Type")) {
}
}
- private static XmlDocument CreateIndexStub() {
+ private XmlDocument CreateIndexStub()
+ {
XmlDocument index = new XmlDocument();
XmlElement index_root = index.CreateElement("Overview");
index.AppendChild(index_root);
- if (assemblies.Length == 0)
+ if (assemblies.Count == 0)
throw new Exception ("No assembly");
XmlElement index_assemblies = index.CreateElement("Assemblies");
index_remarks.InnerText = "To be added.";
index_docs.AppendChild(index_remarks);
- using (TextWriter writer = OpenWrite (outdir + "/ns-" + ns + ".xml", FileMode.CreateNew)) {
- WriteXml(index.DocumentElement, writer);
- }
+ WriteFile (outdir + "/ns-" + ns + ".xml", FileMode.CreateNew,
+ writer => WriteXml (index.DocumentElement, writer));
}
- public static void DoUpdateTypes(string basepath, string[] typenames, string dest) {
- ArrayList found = new ArrayList ();
- foreach (Assembly assembly in assemblies) {
- foreach (DocsTypeInfo docsTypeInfo in GetTypes (assembly, typenames)) {
- string relpath = DoUpdateType (docsTypeInfo.Type, basepath, dest, docsTypeInfo.EcmaDocs);
- if (relpath != null)
- found.Add (docsTypeInfo.Type.FullName);
+ public void DoUpdateTypes (string basepath, List<string> typenames, string dest)
+ {
+ var index = CreateIndexForTypes (dest);
+
+ var found = new HashSet<string> ();
+ foreach (AssemblyDefinition assembly in assemblies) {
+ foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, typenames)) {
+ string relpath = DoUpdateType (type, basepath, dest);
+ if (relpath == null)
+ continue;
+
+ found.Add (type.FullName);
+
+ if (index == null)
+ continue;
+
+ index.Add (assembly);
+ index.Add (type);
}
}
- StringList notFound = new StringList (typenames.Length);
- foreach (string typename in typenames)
- if (!found.Contains (typename))
- notFound.Add (typename);
- if (notFound.Count > 0)
- throw new InvalidOperationException("Type(s) not found: " + string.Join (", ", DocUtils.ToStringArray (notFound)));
+
+ if (index != null)
+ index.Write ();
+
+ if (ignore_missing_types)
+ return;
+
+ var notFound = from n in typenames where !found.Contains (n) select n;
+ if (notFound.Any ())
+ throw new InvalidOperationException("Type(s) not found: " + string.Join (", ", notFound.ToArray ()));
+ }
+
+ class IndexForTypes {
+
+ MDocUpdater app;
+ string indexFile;
+
+ XmlDocument index;
+ XmlElement index_types;
+ XmlElement index_assemblies;
+
+ public IndexForTypes (MDocUpdater app, string indexFile, XmlDocument index)
+ {
+ this.app = app;
+ this.indexFile = indexFile;
+ this.index = index;
+
+ index_types = WriteElement (index.DocumentElement, "Types");
+ index_assemblies = WriteElement (index.DocumentElement, "Assemblies");
+ }
+
+ public void Add (AssemblyDefinition assembly)
+ {
+ if (index_assemblies.SelectSingleNode ("Assembly[@Name='" + assembly.Name.Name + "']") != null)
+ return;
+
+ app.AddIndexAssembly (assembly, index_assemblies);
+ }
+
+ public void Add (TypeDefinition type)
+ {
+ app.AddIndexType (type, index_types);
+ }
+
+ public void Write ()
+ {
+ SortIndexEntries (index_types);
+ WriteFile (indexFile, FileMode.Create,
+ writer => WriteXml (index.DocumentElement, writer));
+ }
+ }
+
+ IndexForTypes CreateIndexForTypes (string dest)
+ {
+ string indexFile = Path.Combine (dest, "index.xml");
+ if (File.Exists (indexFile))
+ return null;
+ return new IndexForTypes (this, indexFile, CreateIndexStub ());
}
- public static string DoUpdateType(Type type, string basepath, string dest, XmlReader ecmaDocsType)
+ public string DoUpdateType (TypeDefinition type, string basepath, string dest)
{
if (type.Namespace == null)
- Error ("warning: The type `{0}' is in the root namespace. This may cause problems with display within monodoc.",
+ Warning ("warning: The type `{0}' is in the root namespace. This may cause problems with display within monodoc.",
type.FullName);
if (!IsPublic (type))
return null;
// Must get the A+B form of the type name.
string typename = GetTypeFileName(type);
- string reltypefile = DocUtils.PathCombine (type.Namespace, typename + ".xml");
+ string reltypefile = DocUtils.PathCombine (DocUtils.GetNamespace (type), typename + ".xml");
string typefile = Path.Combine (basepath, reltypefile);
System.IO.FileInfo file = new System.IO.FileInfo(typefile);
if (file.Exists) {
// Update
XmlDocument basefile = new XmlDocument();
- if (!pretty) basefile.PreserveWhitespace = true;
try {
basefile.Load(typefile);
} catch (Exception e) {
throw new InvalidOperationException("Error loading " + typefile + ": " + e.Message, e);
}
- DoUpdateType2("Updating", basefile, type, output, false, ecmaDocsType);
+ DoUpdateType2("Updating", basefile, type, output, false);
} else {
// Stub
- XmlElement td = StubType(type, output, ecmaDocsType);
+ XmlElement td = StubType(type, output);
if (td == null)
return null;
return reltypefile;
}
- private static XPathNavigator SelectSingleNode (XPathNavigator n, string xpath)
+ public void DoUpdateNS (string ns, string nspath, string outpath)
{
-#if !NET_1_0
- return n.SelectSingleNode (xpath);
-#else
- XPathNodeIterator i = n.Select (xpath);
- XPathNavigator r = null;
- while (i.MoveNext ()) {
- r = i.Current;
- }
- return r;
-#endif
- }
+ Dictionary<TypeDefinition, object> seenTypes = new Dictionary<TypeDefinition,object> ();
+ AssemblyDefinition assembly = assemblies [0];
- public static void DoUpdateNS(string ns, string nspath, string outpath) {
- Hashtable seenTypes = new Hashtable();
- Assembly assembly = assemblies [0];
-
foreach (System.IO.FileInfo file in new System.IO.DirectoryInfo(nspath).GetFiles("*.xml")) {
XmlDocument basefile = new XmlDocument();
- if (!pretty) basefile.PreserveWhitespace = true;
string typefile = Path.Combine(nspath, file.Name);
try {
basefile.Load(typefile);
string typename =
GetTypeFileName (basefile.SelectSingleNode("Type/@FullName").InnerText);
- Type type = assembly.GetType(typename, false);
+ TypeDefinition type = assembly.GetType(typename);
if (type == null) {
- Error ("Type no longer in assembly: " + typename);
+ Warning ("Type no longer in assembly: " + typename);
continue;
}
seenTypes[type] = seenTypes;
- DoUpdateType2("Updating", basefile, type, Path.Combine(outpath, file.Name), false, null);
+ DoUpdateType2("Updating", basefile, type, Path.Combine(outpath, file.Name), false);
}
// Stub types not in the directory
- foreach (DocsTypeInfo docsTypeInfo in GetTypes (assembly, null)) {
- Type type = docsTypeInfo.Type;
+ foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, null)) {
if (type.Namespace != ns || seenTypes.ContainsKey(type))
continue;
- XmlElement td = StubType(type, Path.Combine(outpath, GetTypeFileName(type) + ".xml"), docsTypeInfo.EcmaDocs);
+ XmlElement td = StubType(type, Path.Combine(outpath, GetTypeFileName(type) + ".xml"));
if (td == null) continue;
}
}
- private static string GetTypeFileName(Type type) {
+ private static string GetTypeFileName (TypeReference type)
+ {
return filenameFormatter.GetName (type);
}
return filename.ToString ();
}
-
- private static void AddIndexAssembly (Assembly assembly, XmlElement parent)
+ private void AddIndexAssembly (AssemblyDefinition assembly, XmlElement parent)
{
XmlElement index_assembly = parent.OwnerDocument.CreateElement("Assembly");
- index_assembly.SetAttribute("Name", assembly.GetName().Name);
- index_assembly.SetAttribute("Version", assembly.GetName().Version.ToString());
- MakeAttributes(index_assembly, assembly, true);
+ index_assembly.SetAttribute ("Name", assembly.Name.Name);
+ index_assembly.SetAttribute ("Version", assembly.Name.Version.ToString());
+
+ AssemblyNameDefinition name = assembly.Name;
+ if (name.HasPublicKey) {
+ XmlElement pubkey = parent.OwnerDocument.CreateElement ("AssemblyPublicKey");
+ var key = new StringBuilder (name.PublicKey.Length*3 + 2);
+ key.Append ("[");
+ foreach (byte b in name.PublicKey)
+ key.AppendFormat ("{0,2:x2} ", b);
+ key.Append ("]");
+ pubkey.InnerText = key.ToString ();
+ index_assembly.AppendChild (pubkey);
+ }
+
+ if (!string.IsNullOrEmpty (name.Culture)) {
+ XmlElement culture = parent.OwnerDocument.CreateElement ("AssemblyCulture");
+ culture.InnerText = name.Culture;
+ index_assembly.AppendChild (culture);
+ }
+
+ MakeAttributes (index_assembly, GetCustomAttributes (assembly.CustomAttributes, ""));
parent.AppendChild(index_assembly);
}
- private static void DoUpdateAssemblies (string source, string dest)
+ private void AddIndexType (TypeDefinition type, XmlElement index_types)
+ {
+ string typename = GetTypeFileName(type);
+
+ // Add namespace and type nodes into the index file as needed
+ string ns = DocUtils.GetNamespace (type);
+ XmlElement nsnode = (XmlElement) index_types.SelectSingleNode ("Namespace[@Name='" + ns + "']");
+ if (nsnode == null) {
+ nsnode = index_types.OwnerDocument.CreateElement("Namespace");
+ nsnode.SetAttribute ("Name", ns);
+ index_types.AppendChild (nsnode);
+ }
+ string doc_typename = GetDocTypeName (type);
+ XmlElement typenode = (XmlElement) nsnode.SelectSingleNode ("Type[@Name='" + typename + "']");
+ if (typenode == null) {
+ typenode = index_types.OwnerDocument.CreateElement ("Type");
+ typenode.SetAttribute ("Name", typename);
+ nsnode.AppendChild (typenode);
+ }
+ if (typename != doc_typename)
+ typenode.SetAttribute("DisplayName", doc_typename);
+ else
+ typenode.RemoveAttribute("DisplayName");
+
+ typenode.SetAttribute ("Kind", GetTypeKind (type));
+ }
+
+ private void DoUpdateAssemblies (string source, string dest)
{
string indexfile = dest + "/index.xml";
XmlDocument index;
index = CreateIndexStub();
}
- if (name == null) {
- string defaultTitle = "Untitled";
- if (assemblies.Length == 1)
- defaultTitle = assemblies[0].GetName().Name;
- WriteElementInitialText(index.DocumentElement, "Title", defaultTitle);
- } else {
- WriteElementText(index.DocumentElement, "Title", name);
- }
+ string defaultTitle = "Untitled";
+ if (assemblies.Count == 1)
+ defaultTitle = assemblies[0].Name.Name;
+ WriteElementInitialText(index.DocumentElement, "Title", defaultTitle);
XmlElement index_types = WriteElement(index.DocumentElement, "Types");
XmlElement index_assemblies = WriteElement(index.DocumentElement, "Assemblies");
index_assemblies.RemoveAll ();
-
- Hashtable goodfiles = new Hashtable();
- foreach (Assembly assm in assemblies) {
+
+ HashSet<string> goodfiles = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
+
+ foreach (AssemblyDefinition assm in assemblies) {
AddIndexAssembly (assm, index_assemblies);
DoUpdateAssembly (assm, index_types, source, dest, goodfiles);
}
CleanupIndexTypes (index_types, goodfiles);
CleanupExtensions (index_types);
- using (TextWriter writer = OpenWrite (indexfile, FileMode.Create))
- WriteXml(index.DocumentElement, writer);
+ WriteFile (indexfile, FileMode.Create,
+ writer => WriteXml(index.DocumentElement, writer));
}
private static char[] InvalidFilenameChars = {'\\', '/', ':', '*', '?', '"', '<', '>', '|'};
- private static void DoUpdateAssembly (Assembly assembly, XmlElement index_types, string source, string dest, Hashtable goodfiles)
+ private void DoUpdateAssembly (AssemblyDefinition assembly, XmlElement index_types, string source, string dest, HashSet<string> goodfiles)
{
- foreach (DocsTypeInfo docTypeInfo in GetTypes (assembly, null)) {
- Type type = docTypeInfo.Type;
- if (!IsPublic (type) || type.FullName.IndexOfAny (InvalidFilenameChars) >= 0)
+ foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, null)) {
+ string typename = GetTypeFileName(type);
+ if (!IsPublic (type) || typename.IndexOfAny (InvalidFilenameChars) >= 0 || forwardedTypes.Contains (type.FullName))
continue;
- string reltypepath = DoUpdateType (type, source, dest, docTypeInfo.EcmaDocs);
+ string reltypepath = DoUpdateType (type, source, dest);
if (reltypepath == null)
continue;
// Add namespace and type nodes into the index file as needed
- XmlElement nsnode = (XmlElement)index_types.SelectSingleNode("Namespace[@Name='" + type.Namespace + "']");
- if (nsnode == null) {
- nsnode = index_types.OwnerDocument.CreateElement("Namespace");
- nsnode.SetAttribute("Name", type.Namespace);
- index_types.AppendChild(nsnode);
- }
- string typename = GetTypeFileName(type);
- string doc_typename = GetDocTypeName (type);
- XmlElement typenode = (XmlElement)nsnode.SelectSingleNode("Type[@Name='" + typename + "']");
- if (typenode == null) {
- typenode = index_types.OwnerDocument.CreateElement("Type");
- typenode.SetAttribute("Name", typename);
- nsnode.AppendChild(typenode);
- }
- if (typename != doc_typename)
- typenode.SetAttribute("DisplayName", doc_typename);
- else
- typenode.RemoveAttribute("DisplayName");
- typenode.SetAttribute ("Kind", GetTypeKind (type));
+ AddIndexType (type, index_types);
// Ensure the namespace index file exists
string onsdoc = DocUtils.PathCombine (dest, type.Namespace + ".xml");
WriteNamespaceStub(type.Namespace, dest);
}
- // mark the file as corresponding to a type
- goodfiles[reltypepath] = goodfiles;
- }
- }
-
- class DocsTypeInfo {
- public Type Type;
- public XmlReader EcmaDocs;
-
- public DocsTypeInfo (Type type, XmlReader docs)
- {
- this.Type = type;
- this.EcmaDocs = docs;
- }
- }
-
- static
-#if NET_1_0
- IEnumerable
-#else
- IEnumerable<Mono.Documentation.MDocUpdater.DocsTypeInfo>
-#endif
- GetTypes (Assembly assembly, string[] forTypes)
- {
- Hashtable seen = null;
- if (forTypes != null)
- Array.Sort (forTypes);
- if (ecmadocs != null) {
- seen = new Hashtable ();
- int typeDepth = -1;
- while (ecmadocs.Read ()) {
- switch (ecmadocs.Name) {
- case "Type": {
- if (typeDepth == -1)
- typeDepth = ecmadocs.Depth;
- if (ecmadocs.NodeType != XmlNodeType.Element)
- continue;
- if (typeDepth != ecmadocs.Depth) // nested <Type/> element?
- continue;
- string typename = ecmadocs.GetAttribute ("FullName");
- string typename2 = GetTypeFileName (typename);
- if (forTypes != null &&
- Array.BinarySearch (forTypes, typename) < 0 &&
- typename != typename2 &&
- Array.BinarySearch (forTypes, typename2) < 0)
- continue;
- Type t;
- if ((t = assembly.GetType (typename, false)) == null &&
- (t = assembly.GetType (typename2, false)) == null)
- continue;
- seen.Add (typename, "");
- if (typename != typename2)
- seen.Add (typename2, "");
- Console.WriteLine (" Import: {0}", t.FullName);
- yield return new DocsTypeInfo (t, ecmadocs);
- break;
- }
- default:
- break;
- }
- }
- }
- foreach (Type type in assembly.GetTypes()) {
- if (forTypes != null && Array.BinarySearch (forTypes, type.FullName) < 0)
- continue;
- if (seen != null && seen.ContainsKey (type.FullName))
- continue;
- yield return new DocsTypeInfo (type, null);
+ goodfiles.Add (reltypepath);
}
}
}
}
- abstract class XmlNodeComparer : IComparer
-#if !NET_1_0
- , IComparer<XmlNode>
-#endif
+ abstract class XmlNodeComparer : IComparer, IComparer<XmlNode>
{
public abstract int Compare (XmlNode x, XmlNode y);
}
class AttributeNameComparer : XmlNodeComparer {
+ string attribute;
+
+ public AttributeNameComparer ()
+ : this ("Name")
+ {
+ }
+
+ public AttributeNameComparer (string attribute)
+ {
+ this.attribute = attribute;
+ }
+
public override int Compare (XmlNode x, XmlNode y)
{
- return x.Attributes ["Name"].Value.CompareTo (y.Attributes ["Name"].Value);
+ return x.Attributes [attribute].Value.CompareTo (y.Attributes [attribute].Value);
}
}
}
}
- private static string GetTypeKind (Type type)
+ private static string GetTypeKind (TypeDefinition type)
{
if (type.IsEnum)
return "Enumeration";
return "Structure";
if (type.IsInterface)
return "Interface";
- if (IsDelegate (type))
+ if (DocUtils.IsDelegate (type))
return "Delegate";
- if (type.IsClass || type == typeof(System.Enum))
+ if (type.IsClass || type.FullName == "System.Enum") // FIXME
return "Class";
throw new ArgumentException ("Unknown kind for type: " + type.FullName);
}
- private static bool IsPublic (Type type)
+ private static bool IsPublic (TypeDefinition type)
{
- Type decl = type;
+ TypeDefinition decl = type;
while (decl != null) {
- if (!(decl.IsPublic || decl.IsNestedPublic)) {
+ if (!(decl.IsPublic || decl.IsNestedPublic ||
+ decl.IsNestedFamily || decl.IsNestedFamily || decl.IsNestedFamilyOrAssembly)) {
return false;
}
- decl = decl.DeclaringType;
+ decl = (TypeDefinition) decl.DeclaringType;
}
return true;
}
- private static void CleanupFiles (string dest, Hashtable goodfiles)
+ private void CleanupFiles (string dest, HashSet<string> goodfiles)
{
// Look for files that no longer correspond to types
foreach (System.IO.DirectoryInfo nsdir in new System.IO.DirectoryInfo(dest).GetDirectories("*")) {
foreach (System.IO.FileInfo typefile in nsdir.GetFiles("*.xml")) {
string relTypeFile = Path.Combine(nsdir.Name, typefile.Name);
- if (!goodfiles.ContainsKey(relTypeFile)) {
+ if (!goodfiles.Contains (relTypeFile)) {
XmlDocument doc = new XmlDocument ();
doc.Load (typefile.FullName);
XmlElement e = doc.SelectSingleNode("/Type") as XmlElement;
- if (UpdateAssemblyVersions(e, GetAssemblyVersions(), false)) {
+ if (!no_assembly_versions && UpdateAssemblyVersions(e, GetAssemblyVersions(), false)) {
using (TextWriter writer = OpenWrite (typefile.FullName, FileMode.Truncate))
WriteXml(doc.DocumentElement, writer);
- goodfiles [relTypeFile] = goodfiles;
+ goodfiles.Add (relTypeFile);
continue;
}
string newname = typefile.FullName + ".remove";
try { System.IO.File.Delete(newname); } catch (Exception) { }
- try { typefile.MoveTo(newname); } catch (Exception) { }
+ try { typefile.MoveTo(newname); } catch (Exception) { }
Console.WriteLine("Class no longer present; file renamed: " + Path.Combine(nsdir.Name, typefile.Name));
}
}
private static TextWriter OpenWrite (string path, FileMode mode)
{
- return new StreamWriter (
+ var w = new StreamWriter (
new FileStream (path, mode),
new UTF8Encoding (false)
);
+ w.NewLine = "\n";
+ return w;
}
- private static string[] GetAssemblyVersions ()
+ private string[] GetAssemblyVersions ()
{
- StringList versions = new StringList (assemblies.Length);
- for (int i = 0; i < assemblies.Length; ++i)
- versions.Add (GetAssemblyVersion (assemblies [i]));
- return DocUtils.ToStringArray (versions);
+ return (from a in assemblies select GetAssemblyVersion (a)).ToArray ();
}
-
- private static void CleanupIndexTypes (XmlElement index_types, Hashtable goodfiles)
+
+ private static void CleanupIndexTypes (XmlElement index_types, HashSet<string> goodfiles)
{
// Look for type nodes that no longer correspond to types
MyXmlNodeList remove = new MyXmlNodeList ();
foreach (XmlElement typenode in index_types.SelectNodes("Namespace/Type")) {
string fulltypename = Path.Combine (((XmlElement)typenode.ParentNode).GetAttribute("Name"), typenode.GetAttribute("Name") + ".xml");
- if (!goodfiles.ContainsKey(fulltypename)) {
+ if (!goodfiles.Contains (fulltypename)) {
remove.Add (typenode);
}
}
n.ParentNode.RemoveChild (n);
}
- private static void CleanupExtensions (XmlElement index_types)
+ private void CleanupExtensions (XmlElement index_types)
{
XmlNode e = index_types.SelectSingleNode ("/Overview/ExtensionMethods");
if (extensionMethods.Count == 0) {
if (e == null)
return;
- index_types.RemoveChild (e);
+ index_types.SelectSingleNode ("/Overview").RemoveChild (e);
return;
}
if (e == null) {
static readonly XmlNodeComparer DefaultExtensionMethodComparer = new ExtensionMethodComparer ();
- public static void DoUpdateType2(string message, XmlDocument basefile, Type type, string output, bool insertSince, XmlReader ecmaDocsType) {
+ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition type, string output, bool insertSince)
+ {
Console.WriteLine(message + ": " + type.FullName);
StringToXmlNodeMap seenmembers = new StringToXmlNodeMap ();
// Update type metadata
- UpdateType(basefile.DocumentElement, type, ecmaDocsType);
-
- if (ecmaDocsType != null) {
- while (ecmaDocsType.Name != "Members" && ecmaDocsType.Read ()) {
- // do nothing
- }
- if (ecmaDocsType.IsEmptyElement)
- ecmaDocsType = null;
- }
+ UpdateType(basefile.DocumentElement, type);
// Update existing members. Delete member nodes that no longer should be there,
// and remember what members are already documented so we don't add them again.
- if (!ignoremembers) {
+ if (true) {
MyXmlNodeList todelete = new MyXmlNodeList ();
- foreach (DocsNodeInfo info in GetDocumentationMembers (basefile, type, ecmaDocsType)) {
+ foreach (DocsNodeInfo info in docEnum.GetDocumentationMembers (basefile, type)) {
XmlElement oldmember = info.Node;
- MemberInfo oldmember2 = info.Member;
- string sig = oldmember2 != null ? MakeMemberSignature(oldmember2) : null;
+ MemberReference oldmember2 = info.Member;
+ string sig = oldmember2 != null ? memberFormatters [0].GetDeclaration (oldmember2) : null;
// Interface implementations and overrides are deleted from the docs
// unless the overrides option is given.
- if (oldmember2 != null && (!IsNew(oldmember2) || sig == null))
+ if (oldmember2 != null && sig == null)
oldmember2 = null;
// Deleted (or signature changed)
if (oldmember2 == null) {
- if (UpdateAssemblyVersions (oldmember, new string[]{GetAssemblyVersion (type.Assembly)}, false))
+ if (!no_assembly_versions && UpdateAssemblyVersions (oldmember, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, false))
continue;
DeleteMember ("Member Removed", output, oldmember, todelete);
continue;
else if (DefaultMemberComparer.Compare (oldmember, seenmembers [sig]) == 0)
DeleteMember ("Duplicate Member Found", output, oldmember, todelete);
else
- Error ("TODO: found a duplicate member '{0}', but it's not identical to the prior member found!", sig);
+ Warning ("TODO: found a duplicate member '{0}', but it's not identical to the prior member found!", sig);
continue;
}
oldmember.ParentNode.RemoveChild (oldmember);
}
- if (!IsDelegate(type) && !ignoremembers) {
+ if (!DocUtils.IsDelegate (type)) {
XmlNode members = WriteElement (basefile.DocumentElement, "Members");
- foreach (MemberInfo m in Sort (type.GetMembers(DefaultBindingFlags))) {
- if (m is Type) continue;
+ foreach (MemberReference m in type.GetMembers()) {
+ if (m is TypeDefinition) continue;
- string sig = MakeMemberSignature(m);
+ string sig = memberFormatters [0].GetDeclaration (m);
if (sig == null) continue;
if (seenmembers.ContainsKey(sig)) continue;
- // To be nice on diffs, members/properties/events that are overrides or are interface implementations
- // are not added in.
- if (!IsNew(m)) continue;
-
XmlElement mm = MakeMember(basefile, new DocsNodeInfo (null, m));
if (mm == null) continue;
members.AppendChild( mm );
SortTypeMembers (m);
} while (false);
- System.IO.TextWriter writer;
if (output == null)
- writer = Console.Out;
+ WriteXml(basefile.DocumentElement, Console.Out);
else {
FileInfo file = new FileInfo (output);
if (!file.Directory.Exists) {
Console.WriteLine("Namespace Directory Created: " + type.Namespace);
file.Directory.Create ();
}
- writer = OpenWrite (output, FileMode.Create);
+ WriteFile (output, FileMode.Create,
+ writer => WriteXml(basefile.DocumentElement, writer));
}
-
- using (writer)
- WriteXml(basefile.DocumentElement, writer);
}
- private static string GetCodeSource (string lang, string file)
+ private string GetCodeSource (string lang, string file)
{
int anchorStart;
if (lang == "C#" && (anchorStart = file.IndexOf (".cs#")) >= 0) {
return src.ToString ();
}
} catch (Exception e) {
- Error ("Could not load <code/> file '{0}' region '{1}': {2}",
+ Warning ("Could not load <code/> file '{0}' region '{1}': {2}",
file, region, show_exceptions ? e.ToString () : e.Message);
return null;
}
using (StreamReader reader = new StreamReader (file))
return reader.ReadToEnd ();
} catch (Exception e) {
- Error ("Could not load <code/> file '" + file + "': " + e.Message);
+ Warning ("Could not load <code/> file '" + file + "': " + e.Message);
}
return null;
}
- private static
-#if NET_1_0
- IEnumerable
-#else
- IEnumerable<DocsNodeInfo>
-#endif
- GetDocumentationMembers (XmlDocument basefile, Type type, XmlReader ecmaDocsMembers)
- {
- if (ecmaDocsMembers != null) {
- int membersDepth = ecmaDocsMembers.Depth;
- bool go = true;
- while (go && ecmaDocsMembers.Read ()) {
- switch (ecmaDocsMembers.Name) {
- case "Member": {
- if (membersDepth != ecmaDocsMembers.Depth - 1 || ecmaDocsMembers.NodeType != XmlNodeType.Element)
- continue;
- DocumentationMember dm = new DocumentationMember (ecmaDocsMembers);
- string xp = GetXPathForMember (dm);
- XmlElement oldmember = (XmlElement) basefile.SelectSingleNode (xp);
- MemberInfo m;
- if (oldmember == null) {
- m = GetMember (type, dm);
- if (m == null) {
- Error ("Could not import ECMA docs for `{0}'s `{1}': MemberInfo not found.",
- type.FullName, dm.MemberSignatures ["C#"]);
- // SelectSingleNode (ecmaDocsMember, "MemberSignature[@Language=\"C#\"]/@Value").Value);
- continue;
- }
- // oldmember lookup may have failed due to type parameter renames.
- // Try again.
- oldmember = (XmlElement) basefile.SelectSingleNode (GetXPathForMember (m));
- if (oldmember == null) {
- XmlElement members = WriteElement(basefile.DocumentElement, "Members");
- oldmember = basefile.CreateElement ("Member");
- oldmember.SetAttribute ("MemberName", dm.MemberName);
- members.AppendChild (oldmember);
- foreach (string key in Sort (dm.MemberSignatures.Keys)) {
- XmlElement ms = basefile.CreateElement ("MemberSignature");
- ms.SetAttribute ("Language", key);
- ms.SetAttribute ("Value", (string) dm.MemberSignatures [key]);
- oldmember.AppendChild (ms);
- }
- oldmember.SetAttribute ("__monodocer-seen__", "true");
- Console.WriteLine ("Member Added: {0}", MakeMemberSignature (m));
- additions++;
- }
- }
- else {
- m = GetMember (type, new DocumentationMember (oldmember));
- if (m == null) {
- Error ("Could not import ECMA docs for `{0}'s `{1}': MemberInfo not found.",
- type.FullName, dm.MemberSignatures ["C#"]);
- continue;
- }
- oldmember.SetAttribute ("__monodocer-seen__", "true");
- }
- DocsNodeInfo node = new DocsNodeInfo (oldmember, m);
- if (ecmaDocsMembers.Name != "Docs")
- throw new InvalidOperationException ("Found " + ecmaDocsMembers.Name + "; expected <Docs/>!");
- node.EcmaDocs = ecmaDocsMembers;
- yield return node;
- break;
- }
- case "Members":
- if (membersDepth == ecmaDocsMembers.Depth && ecmaDocsMembers.NodeType == XmlNodeType.EndElement) {
- go = false;
- }
- break;
- }
- }
- }
- foreach (XmlElement oldmember in basefile.SelectNodes("Type/Members/Member")) {
- if (oldmember.GetAttribute ("__monodocer-seen__") == "true") {
- oldmember.RemoveAttribute ("__monodocer-seen__");
- continue;
- }
- MemberInfo m = GetMember (type, new DocumentationMember (oldmember));
- if (m == null) {
- yield return new DocsNodeInfo (oldmember);
- }
- else {
- yield return new DocsNodeInfo (oldmember, m);
- }
- }
- }
-
- static void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList todelete)
+ void DeleteMember (string reason, string output, XmlNode member, MyXmlNodeList todelete)
{
string format = output != null
? "{0}: File='{1}'; Signature='{4}'"
: "{0}: XPath='/Type[@FullName=\"{2}\"]/Members/Member[@MemberName=\"{3}\"]'; Signature='{4}'";
- Error (format,
+ Warning (format,
reason,
output,
member.OwnerDocument.DocumentElement.GetAttribute ("FullName"),
member.Attributes ["MemberName"].Value,
member.SelectSingleNode ("MemberSignature[@Language='C#']/@Value").Value);
if (!delete && MemberDocsHaveUserContent (member)) {
- Error ("Member deletions must be enabled with the --delete option.");
+ Warning ("Member deletions must be enabled with the --delete option.");
} else {
todelete.Add (member);
deletions++;
return false;
}
- private static bool IsNew(MemberInfo m) {
- if (!nooverrides) return true;
- if (m is MethodInfo && !IsNew((MethodInfo)m)) return false;
- if (m is PropertyInfo && !IsNew(((PropertyInfo)m).GetGetMethod())) return false;
- if (m is PropertyInfo && !IsNew(((PropertyInfo)m).GetSetMethod())) return false;
- if (m is EventInfo && !IsNew(((EventInfo)m).GetAddMethod(true))) return false;
- if (m is EventInfo && !IsNew(((EventInfo)m).GetRaiseMethod())) return false;
- if (m is EventInfo && !IsNew(((EventInfo)m).GetRemoveMethod())) return false;
- return true;
- }
-
- private static bool IsNew(MethodInfo m) {
- if (m == null) return true;
- MethodInfo b = m.GetBaseDefinition();
- if (b == null || b == m) return true;
- return false;
- }
-
- // UPDATE HELPER FUNCTIONS
-
-#if false
- private static XmlElement FindMatchingMember(Type type, XmlElement newfile, XmlElement oldmember) {
- MemberInfo oldmember2 = GetMember(type, oldmember.CreateNavigator ());
- if (oldmember2 == null) return null;
-
- string membername = oldmember.GetAttribute("MemberName");
- foreach (XmlElement newmember in newfile.SelectNodes("Members/Member[@MemberName='" + membername + "']")) {
- if (GetMember(type, newmember.CreateNavigator ()) == oldmember2) return newmember;
- }
-
- return null;
- }
-#endif
-
- private static MemberInfo GetMember(Type type, DocumentationMember member) {
- string membertype = member.MemberType;
-
- string returntype = member.ReturnType;
-
- string docName = member.MemberName;
- string[] docTypeParams = GetTypeParameters (docName);
-
- // Loop through all members in this type with the same name
- foreach (MemberInfo mi in GetReflectionMembers (type, docName)) {
- if (mi is Type) continue;
- if (GetMemberType(mi) != membertype) continue;
-
- string sig = MakeMemberSignature(mi);
- if (sig == null) continue; // not publicly visible
-
- ParameterInfo[] pis = null;
- string[] typeParams = null;
- if (mi is MethodInfo || mi is ConstructorInfo) {
- MethodBase mb = (MethodBase) mi;
- pis = mb.GetParameters();
- if (docTypeParams != null && DocUtils.GetContainsGenericParameters (mb)) {
- Type[] args = DocUtils.GetGenericArguments (mb);
- if (args.Length == docTypeParams.Length) {
- typeParams = new string [args.Length];
- for (int i = 0; i < args.Length; ++i)
- typeParams [i] = args [i].Name;
- }
- }
- }
- else if (mi is PropertyInfo)
- pis = ((PropertyInfo)mi).GetIndexParameters();
-
- int mcount = member.Parameters == null ? 0 : member.Parameters.Count;
- int pcount = pis == null ? 0 : pis.Length;
- if (mcount != pcount)
- continue;
-
- if (mi is MethodInfo) {
- // Casting operators can overload based on return type.
- if (returntype != GetReplacedString (
- GetDocTypeFullName (((MethodInfo)mi).ReturnType),
- typeParams, docTypeParams)) {
- continue;
- }
- }
-
- if (pcount == 0)
- return mi;
- bool good = true;
- for (int i = 0; i < pis.Length; i++) {
- string paramType = GetReplacedString (
- GetDocParameterType (pis [i].ParameterType),
- typeParams, docTypeParams);
- if (paramType != (string) member.Parameters [i]) {
- good = false;
- break;
- }
- }
- if (!good) continue;
-
- return mi;
- }
-
- return null;
- }
-
- private static MemberInfoEnumerable GetReflectionMembers (Type type, string docName)
- {
- // need to worry about 4 forms of //@MemberName values:
- // 1. "Normal" (non-generic) member names: GetEnumerator
- // - Lookup as-is.
- // 2. Explicitly-implemented interface member names: System.Collections.IEnumerable.Current
- // - try as-is, and try type.member (due to "kludge" for property
- // support.
- // 3. "Normal" Generic member names: Sort<T> (CSC)
- // - need to remove generic parameters --> "Sort"
- // 4. Explicitly-implemented interface members for generic interfaces:
- // -- System.Collections.Generic.IEnumerable<T>.Current
- // - Try as-is, and try type.member, *keeping* the generic parameters.
- // --> System.Collections.Generic.IEnumerable<T>.Current, IEnumerable<T>.Current
- // 5. As of 2008-01-02, gmcs will do e.g. 'IFoo`1[A].Method' instead of
- // 'IFoo<A>.Method' for explicitly implemented methods; don't interpret
- // this as (1) or (2).
- if (docName.IndexOf ('<') == -1 && docName.IndexOf ('[') == -1) {
- // Cases 1 & 2
- foreach (MemberInfo mi in type.GetMember (docName, DefaultBindingFlags))
- yield return mi;
- if (CountChars (docName, '.') > 0)
- // might be a property; try only type.member instead of
- // namespace.type.member.
- foreach (MemberInfo mi in
- type.GetMember (DocUtils.GetTypeDotMember (docName), DefaultBindingFlags))
- yield return mi;
- yield break;
- }
- // cases 3 & 4
- int numLt = 0;
- int numDot = 0;
- int startLt, startType, startMethod;
- startLt = startType = startMethod = -1;
- for (int i = 0; i < docName.Length; ++i) {
- switch (docName [i]) {
- case '<':
- if (numLt == 0) {
- startLt = i;
- }
- ++numLt;
- break;
- case '>':
- --numLt;
- if (numLt == 0 && (i + 1) < docName.Length)
- // there's another character in docName, so this <...> sequence is
- // probably part of a generic type -- case 4.
- startLt = -1;
- break;
- case '.':
- startType = startMethod;
- startMethod = i;
- ++numDot;
- break;
- }
- }
- string refName = startLt == -1 ? docName : docName.Substring (0, startLt);
- // case 3
- foreach (MemberInfo mi in type.GetMember (refName, DefaultBindingFlags))
- yield return mi;
-
- // case 4
- foreach (MemberInfo mi in type.GetMember (refName.Substring (startType + 1), DefaultBindingFlags))
- yield return mi;
-
- // If we _still_ haven't found it, we've hit another generic naming issue:
- // post Mono 1.1.18, gmcs generates [[FQTN]] instead of <TypeName> for
- // explicitly-implemented METHOD names (not properties), e.g.
- // "System.Collections.Generic.IEnumerable`1[[Foo, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]].GetEnumerator"
- // instead of "System.Collections.Generic.IEnumerable<Foo>.GetEnumerator",
- // which the XML docs will contain.
- //
- // Alas, we can't derive the Mono name from docName, so we need to iterate
- // over all member names, convert them into CSC format, and compare... :-(
- if (numDot == 0)
- yield break;
- foreach (MemberInfo mi in type.GetMembers (DefaultBindingFlags)) {
- if (GetMemberName (mi) == docName)
- yield return mi;
- }
- }
-
- static string[] GetTypeParameters (string docName)
- {
- if (docName [docName.Length-1] != '>')
- return null;
- StringList types = new StringList ();
- int endToken = docName.Length-2;
- int i = docName.Length-2;
- do {
- if (docName [i] == ',' || docName [i] == '<') {
- types.Add (docName.Substring (i + 1, endToken - i));
- endToken = i-1;
- }
- if (docName [i] == '<')
- break;
- } while (--i >= 0);
-
- types.Reverse ();
- return DocUtils.ToStringArray (types);
- }
-
- static string GetReplacedString (string typeName, string[] from, string[] to)
- {
- if (from == null)
- return typeName;
- for (int i = 0; i < from.Length; ++i)
- typeName = typeName.Replace (from [i], to [i]);
- return typeName;
- }
+ // UPDATE HELPER FUNCTIONS
// CREATE A STUB DOCUMENTATION FILE
- public static XmlElement StubType(Type type, string output, XmlReader ecmaDocsType) {
- string typesig = MakeTypeSignature(type);
+ public XmlElement StubType (TypeDefinition type, string output)
+ {
+ string typesig = typeFormatters [0].GetDeclaration (type);
if (typesig == null) return null; // not publicly visible
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("Type");
doc.AppendChild (root);
- DoUpdateType2 ("New Type", doc, type, output, true, ecmaDocsType);
+ DoUpdateType2 ("New Type", doc, type, output, true);
return root;
}
- private static XmlElement CreateSinceNode (XmlDocument doc)
+ private XmlElement CreateSinceNode (XmlDocument doc)
{
XmlElement s = doc.CreateElement ("since");
s.SetAttribute ("version", since);
// STUBBING/UPDATING FUNCTIONS
- public static void UpdateType(XmlElement root, Type type, XmlReader ecmaDocsType) {
+ public void UpdateType (XmlElement root, TypeDefinition type)
+ {
root.SetAttribute("Name", GetDocTypeName (type));
root.SetAttribute("FullName", GetDocTypeFullName (type));
- WriteElementAttribute(root, "TypeSignature[@Language='C#']", "Language", "C#");
- WriteElementAttribute(root, "TypeSignature[@Language='C#']", "Value", MakeTypeSignature(type));
+ foreach (MemberFormatter f in typeFormatters) {
+ string element = "TypeSignature[@Language='" + f.Language + "']";
+ WriteElementAttribute (root, element, "Language", f.Language);
+ WriteElementAttribute (root, element, "Value", f.GetDeclaration (type));
+ }
XmlElement ass = WriteElement(root, "AssemblyInfo");
- WriteElementText(ass, "AssemblyName", type.Assembly.GetName().Name);
- UpdateAssemblyVersions(root, type, true);
- if (type.Assembly.GetName().CultureInfo.Name != "")
- WriteElementText(ass, "AssemblyCulture", type.Assembly.GetName().CultureInfo.Name);
+ WriteElementText(ass, "AssemblyName", type.Module.Assembly.Name.Name);
+ if (!no_assembly_versions) {
+ UpdateAssemblyVersions (root, type, true);
+ }
+ else {
+ var versions = ass.SelectNodes ("AssemblyVersion").Cast<XmlNode> ().ToList ();
+ foreach (var version in versions)
+ ass.RemoveChild (version);
+ }
+ if (!string.IsNullOrEmpty (type.Module.Assembly.Name.Culture))
+ WriteElementText(ass, "AssemblyCulture", type.Module.Assembly.Name.Culture);
else
ClearElement(ass, "AssemblyCulture");
NormalizeWhitespace(ass);
- if (DocUtils.IsGenericType (type)) {
- MakeTypeParameters (root, DocUtils.GetGenericArguments (type));
+ if (type.IsGenericType ()) {
+ MakeTypeParameters (root, type.GenericParameters);
} else {
ClearElement(root, "TypeParameters");
}
WriteElementText(root, "Base/BaseTypeName", basetypename);
// Document how this type instantiates the generic parameters of its base type
- if (DocUtils.IsGenericType (type.BaseType)) {
+ TypeReference origBase = type.BaseType.GetElementType ();
+ if (origBase.IsGenericType ()) {
ClearElement(basenode, "BaseTypeArguments");
- Type[] baseGenArgs = DocUtils.GetGenericArguments (type.BaseType);
- Type genericDefinition = DocUtils.GetGenericTypeDefinition (type.BaseType);
- Type[] genTypeDefArgs = DocUtils.GetGenericArguments (genericDefinition);
- for (int i = 0; i < baseGenArgs.Length; i++) {
- Type typearg = baseGenArgs [i];
- Type typeparam = genTypeDefArgs [i];
-
+ GenericInstanceType baseInst = type.BaseType as GenericInstanceType;
+ IList<TypeReference> baseGenArgs = baseInst == null ? null : baseInst.GenericArguments;
+ IList<GenericParameter> baseGenParams = origBase.GenericParameters;
+ if (baseGenArgs.Count != baseGenParams.Count)
+ throw new InvalidOperationException ("internal error: number of generic arguments doesn't match number of generic parameters.");
+ for (int i = 0; baseGenArgs != null && i < baseGenArgs.Count; i++) {
+ GenericParameter param = baseGenParams [i];
+ TypeReference value = baseGenArgs [i];
+
XmlElement bta = WriteElement(basenode, "BaseTypeArguments");
XmlElement arg = bta.OwnerDocument.CreateElement("BaseTypeArgument");
bta.AppendChild(arg);
- arg.SetAttribute("TypeParamName", typeparam.Name);
- arg.InnerText = GetDocTypeFullName (typearg);
+ arg.SetAttribute ("TypeParamName", param.Name);
+ arg.InnerText = GetDocTypeFullName (value);
}
}
} else {
ClearElement(root, "Base");
}
- if (!IsDelegate(type) && !type.IsEnum) {
- // Get a sorted list of interface implementations. Don't include
- // interfaces that are implemented by a base type or another interface
- // because they go on the base type or base interface's signature.
- ArrayList interface_names = new ArrayList();
- foreach (Type i in type.GetInterfaces())
- if ((type.BaseType == null || Array.IndexOf(type.BaseType.GetInterfaces(), i) == -1) && InterfaceNotFromAnother(i, type.GetInterfaces()))
- interface_names.Add(GetDocTypeFullName (i));
- interface_names.Sort();
+ if (!DocUtils.IsDelegate (type) && !type.IsEnum) {
+ IEnumerable<TypeReference> userInterfaces = DocUtils.GetUserImplementedInterfaces (type);
+ List<string> interface_names = userInterfaces
+ .Select (iface => GetDocTypeFullName (iface))
+ .OrderBy (s => s)
+ .ToList ();
XmlElement interfaces = WriteElement(root, "Interfaces");
interfaces.RemoveAll();
ClearElement(root, "Interfaces");
}
- MakeAttributes(root, type, false);
+ MakeAttributes (root, GetCustomAttributes (type));
- if (IsDelegate(type)) {
- MakeTypeParameters (root, DocUtils.GetGenericArguments (type));
- MakeParameters(root, type.GetMethod("Invoke").GetParameters());
+ if (DocUtils.IsDelegate (type)) {
+ MakeTypeParameters (root, type.GenericParameters);
+ MakeParameters(root, type.GetMethod("Invoke").Parameters);
MakeReturnValue(root, type.GetMethod("Invoke"));
}
DocsNodeInfo typeInfo = new DocsNodeInfo (WriteElement(root, "Docs"), type);
- if (ecmaDocsType != null) {
- if (ecmaDocsType.Name != "Docs") {
- int depth = ecmaDocsType.Depth;
- while (ecmaDocsType.Read ()) {
- if (ecmaDocsType.Name == "Docs" && ecmaDocsType.Depth == depth + 1)
- break;
- }
- }
- if (!ecmaDocsType.IsStartElement ("Docs"))
- throw new InvalidOperationException ("Found " + ecmaDocsType.Name + "; expecting <Docs/>!");
- typeInfo.EcmaDocs = ecmaDocsType;
- }
MakeDocNode (typeInfo);
- if (!IsDelegate (type))
+ if (!DocUtils.IsDelegate (type))
WriteElement (root, "Members");
+ OrderTypeNodes (root, root.ChildNodes);
NormalizeWhitespace(root);
}
- class MemberInfoComparer : IComparer
-#if !NET_1_0
- , IComparer<MemberInfo>
-#endif
- {
- public int Compare (MemberInfo x, MemberInfo y)
- {
- string xs = slashdocFormatter.GetName (x);
- string ys = slashdocFormatter.GetName (y);
- // return String.Compare (xs, ys, StringComparison.OrdinalIgnoreCase);
- return string.Compare (xs, ys, true, CultureInfo.InvariantCulture);
- }
-
- public int Compare (object x, object y)
- {
- return Compare ((MemberInfo) x, (MemberInfo) y);
- }
- }
-
- static MemberInfoComparer memberInfoComparer = new MemberInfoComparer ();
+ static readonly string[] TypeNodeOrder = {
+ "TypeSignature",
+ "MemberOfLibrary",
+ "AssemblyInfo",
+ "ThreadingSafetyStatement",
+ "ThreadSafetyStatement",
+ "TypeParameters",
+ "Base",
+ "Interfaces",
+ "Attributes",
+ "Parameters",
+ "ReturnValue",
+ "Docs",
+ "Members",
+ "TypeExcluded",
+ };
- private static MemberInfo[] Sort (MemberInfo[] members)
+ static void OrderTypeNodes (XmlNode member, XmlNodeList children)
{
-#if NET_1_0
- ArrayList l = new ArrayList ();
- l.AddRange (members);
- l.Sort (memberInfoComparer);
- return (MemberInfo[]) l.ToArray (typeof(MemberInfo));
-#else
- Array.Sort (members, memberInfoComparer);
- return members;
-#endif
+ ReorderNodes (member, children, TypeNodeOrder);
}
-#if NET_1_0
- static IEnumerable Sort (IEnumerable list)
- {
- ArrayList l = new ArrayList (list as ICollection);
- l.Sort ();
- return l;
- }
-#else
- static IEnumerable<T> Sort<T> (IEnumerable<T> list)
+ internal static IEnumerable<T> Sort<T> (IEnumerable<T> list)
{
List<T> l = new List<T> (list);
l.Sort ();
return l;
}
-#endif
-
- private static void UpdateMember(DocsNodeInfo info) {
+
+ private void UpdateMember (DocsNodeInfo info)
+ {
XmlElement me = (XmlElement) info.Node;
- MemberInfo mi = info.Member;
- WriteElementAttribute(me, "MemberSignature[@Language='C#']", "Language", "C#");
- WriteElementAttribute(me, "MemberSignature[@Language='C#']", "Value", MakeMemberSignature(mi));
+ MemberReference mi = info.Member;
+
+ foreach (MemberFormatter f in memberFormatters) {
+ string element = "MemberSignature[@Language='" + f.Language + "']";
+ WriteElementAttribute (me, element, "Language", f.Language);
+ WriteElementAttribute (me, element, "Value", f.GetDeclaration (mi));
+ }
WriteElementText(me, "MemberType", GetMemberType(mi));
- UpdateAssemblyVersions(me, mi, true);
- MakeAttributes(me, mi, false);
+ if (!no_assembly_versions) {
+ UpdateAssemblyVersions (me, mi, true);
+ }
+ else {
+ ClearElement (me, "AssemblyInfo");
+ }
+
+ MakeAttributes (me, GetCustomAttributes (mi));
+
MakeReturnValue(me, mi);
- if (mi is MethodBase) {
- MethodBase mb = (MethodBase) mi;
- if (DocUtils.GetContainsGenericParameters (mb))
- MakeTypeParameters (me, DocUtils.GetGenericArguments (mb));
+ if (mi is MethodReference) {
+ MethodReference mb = (MethodReference) mi;
+ if (mb.IsGenericMethod ())
+ MakeTypeParameters (me, mb.GenericParameters);
}
MakeParameters(me, mi);
string fieldValue;
- if (mi is FieldInfo && GetFieldConstValue((FieldInfo)mi, out fieldValue))
+ if (mi is FieldDefinition && GetFieldConstValue ((FieldDefinition)mi, out fieldValue))
WriteElementText(me, "MemberValue", fieldValue);
info.Node = WriteElement (me, "Docs");
MakeDocNode (info);
+ OrderMemberNodes (me, me.ChildNodes);
UpdateExtensionMethods (me, info);
}
+ static readonly string[] MemberNodeOrder = {
+ "MemberSignature",
+ "MemberType",
+ "AssemblyInfo",
+ "Attributes",
+ "ReturnValue",
+ "TypeParameters",
+ "Parameters",
+ "MemberValue",
+ "Docs",
+ "Excluded",
+ "ExcludedLibrary",
+ "Link",
+ };
+
+ static void OrderMemberNodes (XmlNode member, XmlNodeList children)
+ {
+ ReorderNodes (member, children, MemberNodeOrder);
+ }
+
+ static void ReorderNodes (XmlNode node, XmlNodeList children, string[] ordering)
+ {
+ MyXmlNodeList newChildren = new MyXmlNodeList (children.Count);
+ for (int i = 0; i < ordering.Length; ++i) {
+ for (int j = 0; j < children.Count; ++j) {
+ XmlNode c = children [j];
+ if (c.Name == ordering [i]) {
+ newChildren.Add (c);
+ }
+ }
+ }
+ if (newChildren.Count >= 0)
+ node.PrependChild ((XmlNode) newChildren [0]);
+ for (int i = 1; i < newChildren.Count; ++i) {
+ XmlNode prev = (XmlNode) newChildren [i-1];
+ XmlNode cur = (XmlNode) newChildren [i];
+ node.RemoveChild (cur);
+ node.InsertAfter (cur, prev);
+ }
+ }
+
+ IEnumerable<string> GetCustomAttributes (MemberReference mi)
+ {
+ IEnumerable<string> attrs = Enumerable.Empty<string>();
+
+ ICustomAttributeProvider p = mi as ICustomAttributeProvider;
+ if (p != null)
+ attrs = attrs.Concat (GetCustomAttributes (p.CustomAttributes, ""));
+
+ PropertyDefinition pd = mi as PropertyDefinition;
+ if (pd != null) {
+ if (pd.GetMethod != null)
+ attrs = attrs.Concat (GetCustomAttributes (pd.GetMethod.CustomAttributes, "get: "));
+ if (pd.SetMethod != null)
+ attrs = attrs.Concat (GetCustomAttributes (pd.SetMethod.CustomAttributes, "set: "));
+ }
+
+ EventDefinition ed = mi as EventDefinition;
+ if (ed != null) {
+ if (ed.AddMethod != null)
+ attrs = attrs.Concat (GetCustomAttributes (ed.AddMethod.CustomAttributes, "add: "));
+ if (ed.RemoveMethod != null)
+ attrs = attrs.Concat (GetCustomAttributes (ed.RemoveMethod.CustomAttributes, "remove: "));
+ }
+
+ return attrs;
+ }
+
+ IEnumerable<string> GetCustomAttributes (IList<CustomAttribute> attributes, string prefix)
+ {
+ foreach (CustomAttribute attribute in attributes.OrderBy (ca => ca.AttributeType.FullName)) {
+
+ TypeDefinition attrType = attribute.AttributeType as TypeDefinition;
+ if (attrType != null && !IsPublic (attrType))
+ continue;
+ if (slashdocFormatter.GetName (attribute.AttributeType) == null)
+ continue;
+
+ if (Array.IndexOf (IgnorableAttributes, attribute.AttributeType.FullName) >= 0)
+ continue;
+
+ StringList fields = new StringList ();
+
+ for (int i = 0; i < attribute.ConstructorArguments.Count; ++i) {
+ CustomAttributeArgument argument = attribute.ConstructorArguments [i];
+ fields.Add (MakeAttributesValueString (
+ argument.Value,
+ argument.Type));
+ }
+ var namedArgs =
+ (from namedArg in attribute.Fields
+ select new { Type=namedArg.Argument.Type, Name=namedArg.Name, Value=namedArg.Argument.Value })
+ .Concat (
+ (from namedArg in attribute.Properties
+ select new { Type=namedArg.Argument.Type, Name=namedArg.Name, Value=namedArg.Argument.Value }))
+ .OrderBy (v => v.Name);
+ foreach (var d in namedArgs)
+ fields.Add (string.Format ("{0}={1}", d.Name,
+ MakeAttributesValueString (d.Value, d.Type)));
+
+ string a2 = String.Join(", ", fields.ToArray ());
+ if (a2 != "") a2 = "(" + a2 + ")";
+
+ string name = attribute.GetDeclaringType();
+ if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length-"Attribute".Length);
+ yield return prefix + name + a2;
+ }
+ }
+
static readonly string[] ValidExtensionMembers = {
"Docs",
"MemberSignature",
"typeparam",
};
- private static void UpdateExtensionMethods (XmlElement e, DocsNodeInfo info)
+ private void UpdateExtensionMethods (XmlElement e, DocsNodeInfo info)
{
- MethodInfo me = info.Member as MethodInfo;
+ MethodDefinition me = info.Member as MethodDefinition;
if (me == null)
return;
- if (info.Parameters.Length < 1)
+ if (info.Parameters.Count < 1)
return;
if (!DocUtils.IsExtensionMethod (me))
return;
{
XmlElement targets = member.OwnerDocument.CreateElement ("Targets");
member.PrependChild (targets);
- if (!DocUtils.IsGenericParameter (info.Parameters [0].ParameterType))
+ if (!(info.Parameters [0].ParameterType is GenericParameter)) {
AppendElementAttributeText (targets, "Target", "Type",
slashdocFormatter.GetDeclaration (info.Parameters [0].ParameterType));
+ }
else {
- Type[] constraints = DocUtils.GetGenericParameterConstraints (
- info.Parameters [0].ParameterType);
- if (constraints.Length == 0)
+ GenericParameter gp = (GenericParameter) info.Parameters [0].ParameterType;
+ IList<TypeReference> constraints = gp.Constraints;
+ if (constraints.Count == 0)
AppendElementAttributeText (targets, "Target", "Type", "System.Object");
else
- foreach (Type c in constraints)
+ foreach (TypeReference c in constraints)
AppendElementAttributeText(targets, "Target", "Type",
slashdocFormatter.GetDeclaration (c));
}
}
- private static bool GetFieldConstValue(FieldInfo field, out string value) {
+ private static bool GetFieldConstValue (FieldDefinition field, out string value)
+ {
value = null;
- if (field.DeclaringType.IsEnum) return false;
- if (DocUtils.IsGenericType (field.DeclaringType)) return false;
- if (field.IsLiteral || (field.IsStatic && field.IsInitOnly)) {
- object val;
- try {
- val = field.GetValue(null);
- } catch {
- return false;
- }
+ TypeDefinition type = field.DeclaringType.Resolve ();
+ if (type != null && type.IsEnum) return false;
+
+ if (type != null && type.IsGenericType ()) return false;
+ if (!field.HasConstant)
+ return false;
+ if (field.IsLiteral) {
+ object val = field.Constant;
if (val == null) value = "null";
else if (val is Enum) value = val.ToString();
else if (val is IFormattable) {
// XML HELPER FUNCTIONS
- private static XmlElement WriteElement(XmlNode parent, string element) {
+ internal static XmlElement WriteElement(XmlNode parent, string element) {
XmlElement ret = (XmlElement)parent.SelectSingleNode(element);
if (ret == null) {
string[] path = element.Split('/');
node.InnerText = value;
}
-#if !NET_1_0
static XmlElement AppendElementText (XmlNode parent, string element, string value)
{
XmlElement n = parent.OwnerDocument.CreateElement (element);
n.InnerText = value;
return n;
}
-#endif
static XmlElement AppendElementAttributeText (XmlNode parent, string element, string attribute, string value)
{
return n;
}
- private static XmlNode CopyNode (XmlNode source, XmlNode dest)
+ internal static XmlNode CopyNode (XmlNode source, XmlNode dest)
{
XmlNode copy = dest.OwnerDocument.ImportNode (source, true);
dest.AppendChild (copy);
if (node.GetAttribute(attribute) == value) return;
node.SetAttribute(attribute, value);
}
- private static void ClearElement(XmlElement parent, string name) {
+ internal static void ClearElement(XmlElement parent, string name) {
XmlElement node = (XmlElement)parent.SelectSingleNode(name);
if (node != null)
parent.RemoveChild(node);
// DOCUMENTATION HELPER FUNCTIONS
- private static void MakeDocNode (DocsNodeInfo info)
+ private void MakeDocNode (DocsNodeInfo info)
{
- Type[] genericParams = info.GenericParameters;
- ParameterInfo[] parameters = info.Parameters;
- Type returntype = info.ReturnType;
+ List<GenericParameter> genericParams = info.GenericParameters;
+ IList<ParameterDefinition> parameters = info.Parameters;
+ TypeReference returntype = info.ReturnType;
bool returnisreturn = info.ReturnIsReturn;
XmlElement e = info.Node;
bool addremarks = info.AddRemarks;
WriteElementInitialText(e, "summary", "To be added.");
if (parameters != null) {
- string[] values = new string [parameters.Length];
+ string[] values = new string [parameters.Count];
for (int i = 0; i < values.Length; ++i)
values [i] = parameters [i].Name;
UpdateParameters (e, "param", values);
}
if (genericParams != null) {
- string[] values = new string [genericParams.Length];
+ string[] values = new string [genericParams.Count];
for (int i = 0; i < values.Length; ++i)
values [i] = genericParams [i].Name;
UpdateParameters (e, "typeparam", values);
}
string retnodename = null;
- if (returntype != null && returntype != typeof(void)) {
+ if (returntype != null && returntype.FullName != "System.Void") { // FIXME
retnodename = returnisreturn ? "returns" : "value";
string retnodename_other = !returnisreturn ? "returns" : "value";
if (addremarks)
WriteElementInitialText(e, "remarks", "To be added.");
- if (info.EcmaDocs != null) {
- XmlReader r = info.EcmaDocs;
- int depth = r.Depth;
- r.ReadStartElement ("Docs");
- while (r.Read ()) {
- if (r.Name == "Docs") {
- if (r.Depth == depth && r.NodeType == XmlNodeType.EndElement)
- break;
- else
- throw new InvalidOperationException ("Skipped past current <Docs/> element!");
- }
- if (!r.IsStartElement ())
- continue;
- switch (r.Name) {
- case "param":
- case "typeparam": {
- XmlNode doc = e.SelectSingleNode (
- r.Name + "[@name='" + r.GetAttribute ("name") + "']");
- string value = r.ReadInnerXml ();
- if (doc != null)
- doc.InnerXml = value.Replace ("\r", "");
- break;
- }
- case "altmember":
- case "exception":
- case "permission":
- case "seealso": {
- string name = r.Name;
- string cref = r.GetAttribute ("cref");
- XmlNode doc = e.SelectSingleNode (
- r.Name + "[@cref='" + cref + "']");
- string value = r.ReadInnerXml ().Replace ("\r", "");
- if (doc != null)
- doc.InnerXml = value;
- else {
- XmlElement n = e.OwnerDocument.CreateElement (name);
- n.SetAttribute ("cref", cref);
- n.InnerXml = value;
- e.AppendChild (n);
- }
- break;
- }
- default: {
- string name = r.Name;
- string xpath = r.Name;
- StringList attributes = new StringList (r.AttributeCount);
- if (r.MoveToFirstAttribute ()) {
- do {
- attributes.Add ("@" + r.Name + "=\"" + r.Value + "\"");
- } while (r.MoveToNextAttribute ());
- r.MoveToContent ();
- }
- if (attributes.Count > 0) {
- xpath += "[" + string.Join (" and ", DocUtils.ToStringArray (attributes)) + "]";
- }
- XmlNode doc = e.SelectSingleNode (xpath);
- string value = r.ReadInnerXml ().Replace ("\r", "");
- if (doc != null) {
- doc.InnerXml = value;
- }
- else {
- XmlElement n = e.OwnerDocument.CreateElement (name);
- n.InnerXml = value;
- foreach (string a in attributes) {
- int eq = a.IndexOf ('=');
- n.SetAttribute (a.Substring (1, eq-1), a.Substring (eq+2, a.Length-eq-3));
- }
- e.AppendChild (n);
- }
- break;
- }
- }
- }
- }
- if (info.SlashDocs != null) {
- XmlNode elem = info.SlashDocs;
- if (elem != null) {
- if (elem.SelectSingleNode("summary") != null)
- ClearElement(e, "summary");
- if (elem.SelectSingleNode("remarks") != null)
- ClearElement(e, "remarks");
- if (elem.SelectSingleNode("value") != null)
- ClearElement(e, "value");
- if (retnodename != null && elem.SelectSingleNode(retnodename) != null)
- ClearElement(e, retnodename);
-
- foreach (XmlNode child in elem.ChildNodes) {
- switch (child.Name) {
- case "param":
- case "typeparam": {
- XmlElement p2 = (XmlElement) e.SelectSingleNode (child.Name + "[@name='" + child.Attributes ["name"].Value + "']");
- if (p2 != null)
- p2.InnerXml = child.InnerXml;
- break;
- }
- case "altmember":
- case "exception":
- case "permission": {
- XmlElement a = (XmlElement) e.SelectSingleNode (child.Name + "[@cref='" + child.Attributes ["cref"].Value + "']");
- if (a == null) {
- a = e.OwnerDocument.CreateElement (child.Name);
- a.SetAttribute ("cref", child.Attributes ["cref"].Value);
- e.AppendChild (a);
- }
- a.InnerXml = child.InnerXml;
- break;
- }
- case "seealso": {
- XmlElement a = (XmlElement) e.SelectSingleNode ("altmember[@cref='" + child.Attributes ["cref"].Value + "']");
- if (a == null) {
- a = e.OwnerDocument.CreateElement ("altmember");
- a.SetAttribute ("cref", child.Attributes ["cref"].Value);
- e.AppendChild (a);
- }
- break;
- }
- default:
- CopyNode (child, e);
- break;
- }
- }
- }
+ if (exceptions.HasValue && info.Member != null &&
+ (exceptions.Value & ExceptionLocations.AddedMembers) == 0) {
+ UpdateExceptions (e, info.Member);
}
+
+ foreach (DocumentationImporter importer in importers)
+ importer.ImportDocumentation (info);
OrderDocsNodes (e, e.ChildNodes);
NormalizeWhitespace(e);
private static void OrderDocsNodes (XmlNode docs, XmlNodeList children)
{
- MyXmlNodeList newChildren = new MyXmlNodeList (children.Count);
- for (int i = 0; i < DocsNodeOrder.Length; ++i) {
- for (int j = 0; j < children.Count; ++j) {
- XmlNode c = children [j];
- if (c.Name == DocsNodeOrder [i]) {
- newChildren.Add (c);
- }
- }
- }
- if (newChildren.Count >= 0)
- docs.PrependChild ((XmlNode) newChildren [0]);
- for (int i = 1; i < newChildren.Count; ++i) {
- XmlNode prev = (XmlNode) newChildren [i-1];
- XmlNode cur = (XmlNode) newChildren [i];
- docs.RemoveChild (cur);
- docs.InsertAfter (cur, prev);
- }
+ ReorderNodes (docs, children, DocsNodeOrder);
}
- private static void UpdateParameters (XmlElement e, string element, string[] values)
+ private void UpdateParameters (XmlElement e, string element, string[] values)
{
if (values != null) {
XmlNode[] paramnodes = new XmlNode[values.Length];
string name = paramnode.GetAttribute("name");
if (!seenParams.ContainsKey(name)) {
if (!delete && !paramnode.InnerText.StartsWith("To be added")) {
- Error ("The following param node can only be deleted if the --delete option is given: ");
+ Warning ("The following param node can only be deleted if the --delete option is given: ");
if (e.ParentNode == e.OwnerDocument.DocumentElement) {
// delegate type
- Error ("\tXPath=/Type[@FullName=\"{0}\"]/Docs/param[@name=\"{1}\"]",
+ Warning ("\tXPath=/Type[@FullName=\"{0}\"]/Docs/param[@name=\"{1}\"]",
e.OwnerDocument.DocumentElement.GetAttribute ("FullName"),
name);
}
else {
- Error ("\tXPath=/Type[@FullName=\"{0}\"]//Member[@MemberName=\"{1}\"]/Docs/param[@name=\"{2}\"]",
+ Warning ("\tXPath=/Type[@FullName=\"{0}\"]//Member[@MemberName=\"{1}\"]/Docs/param[@name=\"{2}\"]",
e.OwnerDocument.DocumentElement.GetAttribute ("FullName"),
e.ParentNode.Attributes ["MemberName"].Value,
name);
}
- Error ("\tValue={0}", paramnode.OuterXml);
+ Warning ("\tValue={0}", paramnode.OuterXml);
} else {
todelete.Add (paramnode);
}
paramref.SetAttribute ("name", newName);
}
+ class CrefComparer : XmlNodeComparer {
+
+ public CrefComparer ()
+ {
+ }
+
+ public override int Compare (XmlNode x, XmlNode y)
+ {
+ string xType = x.Attributes ["cref"].Value;
+ string yType = y.Attributes ["cref"].Value;
+ string xNamespace = GetNamespace (xType);
+ string yNamespace = GetNamespace (yType);
+
+ int c = xNamespace.CompareTo (yNamespace);
+ if (c != 0)
+ return c;
+ return xType.CompareTo (yType);
+ }
+
+ static string GetNamespace (string type)
+ {
+ int n = type.LastIndexOf ('.');
+ if (n >= 0)
+ return type.Substring (0, n);
+ return string.Empty;
+ }
+ }
+
+ private void UpdateExceptions (XmlNode docs, MemberReference member)
+ {
+ foreach (var source in new ExceptionLookup (exceptions.Value)[member]) {
+ string cref = slashdocFormatter.GetDeclaration (source.Exception);
+ var node = docs.SelectSingleNode ("exception[@cref='" + cref + "']");
+ if (node != null)
+ continue;
+ XmlElement e = docs.OwnerDocument.CreateElement ("exception");
+ e.SetAttribute ("cref", cref);
+ e.InnerXml = "To be added; from: <see cref=\"" +
+ string.Join ("\" />, <see cref=\"",
+ source.Sources.Select (m => slashdocFormatter.GetDeclaration (m))
+ .ToArray ()) +
+ "\" />";
+ docs.AppendChild (e);
+ }
+ SortXmlNodes (docs, docs.SelectNodes ("exception"),
+ new CrefComparer ());
+ }
+
private static void NormalizeWhitespace(XmlElement e) {
// Remove all text and whitespace nodes from the element so it
// is outputted with nice indentation and no blank lines.
n.ParentNode.RemoveChild(n);
}
- private static bool UpdateAssemblyVersions(XmlElement root, MemberInfo member, bool add)
+ private static bool UpdateAssemblyVersions (XmlElement root, MemberReference member, bool add)
{
- Type type = member as Type;
+ TypeDefinition type = member as TypeDefinition;
if (type == null)
- type = member.DeclaringType;
- return UpdateAssemblyVersions(root, new string[]{ GetAssemblyVersion(type.Assembly) }, add);
+ type = member.DeclaringType as TypeDefinition;
+ return UpdateAssemblyVersions(root, new string[]{ GetAssemblyVersion (type.Module.Assembly) }, add);
}
- private static string GetAssemblyVersion(Assembly assembly)
+ private static string GetAssemblyVersion (AssemblyDefinition assembly)
{
- return assembly.GetName().Version.ToString();
+ return assembly.Name.Version.ToString();
}
private static bool UpdateAssemblyVersions(XmlElement root, string[] assemblyVersions, bool add)
e = root.OwnerDocument.CreateElement("AssemblyInfo");
root.AppendChild(e);
}
- MyXmlNodeList matches = new MyXmlNodeList (assemblyVersions.Length);
- foreach (XmlElement v in e.SelectNodes ("AssemblyVersion")) {
- foreach (string sv in assemblyVersions)
- if (v.InnerText == sv)
- matches.Add (v);
- }
+ List<XmlNode> matches = e.SelectNodes ("AssemblyVersion").Cast<XmlNode>()
+ .Where(v => Array.IndexOf (assemblyVersions, v.InnerText) >= 0)
+ .ToList ();
// matches.Count > 0 && add: ignore -- already present
if (matches.Count > 0 && !add) {
foreach (XmlNode c in matches)
return avs.Count != 0;
}
-#if !NET_1_0
- private static Type[] IgnorableAttributes = {
+ // FIXME: get TypeReferences instead of string comparison?
+ private static string[] IgnorableAttributes = {
// Security related attributes
- typeof (System.Reflection.AssemblyKeyFileAttribute),
- typeof (System.Reflection.AssemblyDelaySignAttribute),
+ "System.Reflection.AssemblyKeyFileAttribute",
+ "System.Reflection.AssemblyDelaySignAttribute",
// Present in @RefType
- typeof (System.Runtime.InteropServices.OutAttribute),
+ "System.Runtime.InteropServices.OutAttribute",
// For naming the indexer to use when not using indexers
- typeof (System.Reflection.DefaultMemberAttribute),
+ "System.Reflection.DefaultMemberAttribute",
// for decimal constants
- typeof (System.Runtime.CompilerServices.DecimalConstantAttribute),
+ "System.Runtime.CompilerServices.DecimalConstantAttribute",
// compiler generated code
- typeof (System.Runtime.CompilerServices.CompilerGeneratedAttribute),
+ "System.Runtime.CompilerServices.CompilerGeneratedAttribute",
// more compiler generated code, e.g. iterator methods
- typeof (System.Diagnostics.DebuggerHiddenAttribute),
- typeof (System.Runtime.CompilerServices.FixedBufferAttribute),
- typeof (System.Runtime.CompilerServices.UnsafeValueTypeAttribute),
+ "System.Diagnostics.DebuggerHiddenAttribute",
+ "System.Runtime.CompilerServices.FixedBufferAttribute",
+ "System.Runtime.CompilerServices.UnsafeValueTypeAttribute",
// extension methods
- typeof (System.Runtime.CompilerServices.ExtensionAttribute),
+ "System.Runtime.CompilerServices.ExtensionAttribute",
+ // Used to differentiate 'object' from C#4 'dynamic'
+ "System.Runtime.CompilerServices.DynamicAttribute",
};
-#endif
- private static void MakeAttributes(XmlElement root, object attributes, bool assemblyAttributes) {
- int len;
-#if NET_1_0
- object[] at = ((ICustomAttributeProvider) attributes).GetCustomAttributes (false);
- len = at.Length;
-#else
- System.Collections.Generic.IList<CustomAttributeData> at;
- if (attributes is Assembly)
- at = CustomAttributeData.GetCustomAttributes((Assembly)attributes);
- else if (attributes is MemberInfo)
- at = CustomAttributeData.GetCustomAttributes((MemberInfo)attributes);
- else if (attributes is Module)
- at = CustomAttributeData.GetCustomAttributes((Module)attributes);
- else if (attributes is ParameterInfo)
- at = CustomAttributeData.GetCustomAttributes((ParameterInfo)attributes);
- else
- throw new ArgumentException("unsupported type: " + attributes.GetType().ToString());
- len = at.Count;
-#endif
-
- if (len == 0) {
- ClearElement(root, "Attributes");
+ private void MakeAttributes (XmlElement root, IEnumerable<string> attributes)
+ {
+ if (!attributes.Any ()) {
+ ClearElement (root, "Attributes");
return;
}
- bool b = false;
XmlElement e = (XmlElement)root.SelectSingleNode("Attributes");
if (e != null)
e.RemoveAll();
- else
+ else if (e == null)
e = root.OwnerDocument.CreateElement("Attributes");
-#if !NET_1_0
- foreach (CustomAttributeData a in at) {
- if (!IsPublic (a.Constructor.DeclaringType))
- continue;
- if (slashdocFormatter.GetName (a.Constructor.DeclaringType) == null)
- continue;
-
- if (Array.IndexOf (IgnorableAttributes, a.Constructor.DeclaringType) >= 0)
- continue;
-
- b = true;
-
- StringList fields = new StringList ();
-
- foreach (CustomAttributeTypedArgument f in a.ConstructorArguments) {
- fields.Add(MakeAttributesValueString(f.Value));
- }
- foreach (CustomAttributeNamedArgument f in a.NamedArguments) {
- fields.Add(f.MemberInfo.Name + "=" + MakeAttributesValueString(f.TypedValue.Value));
- }
-
- string a2 = String.Join(", ", DocUtils.ToStringArray (fields));
- if (a2 != "") a2 = "(" + a2 + ")";
-
+ foreach (string attribute in attributes) {
XmlElement ae = root.OwnerDocument.CreateElement("Attribute");
e.AppendChild(ae);
- string name = a.Constructor.DeclaringType.FullName;
- if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length-"Attribute".Length);
- WriteElementText(ae, "AttributeName", name + a2);
+ WriteElementText(ae, "AttributeName", attribute);
}
-#else
- foreach (Attribute a in at) {
- if (!IsPublic (a.GetType ()))
- continue;
- if (slashdocFormatter.GetName (a.GetType ()) == null) continue; // hide non-visible attributes
- //if (assemblyAttributes && a.GetType().FullName.StartsWith("System.Reflection.")) continue;
- if (a.GetType().FullName == "System.Reflection.AssemblyKeyFileAttribute" || a.GetType().FullName == "System.Reflection.AssemblyDelaySignAttribute") continue; // hide security-related attributes
-
- b = true;
-
- // There's no way to reconstruct how the attribute's constructor was called,
- // so as a substitute, just list the value of all of the attribute's public fields.
-
- StringList fields = new StringList ();
- foreach (PropertyInfo f in a.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance)) {
- if (f.Name == "TypeId") continue;
-
- object v;
- try {
- v = f.GetValue(a, null);
- if (v == null) v = "null";
- else if (v is string) v = "\"" + v + "\"";
- else if (v is Type) v = "typeof(" + GetCSharpFullName ((Type)v) + ")";
- else if (v is Enum) v = v.GetType().FullName + "." + v.ToString().Replace(", ", "|");
- }
- catch (Exception ex) {
- v = "/* error getting property value: " + ex.Message + " */";
- }
-
- fields.Add(f.Name + "=" + v);
- }
- string a2 = String.Join(", ", DocUtils.ToStringArray (fields));
- if (a2 != "") a2 = "(" + a2 + ")";
-
- XmlElement ae = root.OwnerDocument.CreateElement("Attribute");
- e.AppendChild(ae);
-
- string name = a.GetType().FullName;
- if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length-"Attribute".Length);
- WriteElementText(ae, "AttributeName", name + a2);
- }
-#endif
- if (b && e.ParentNode == null)
+ if (e.ParentNode == null)
root.AppendChild(e);
- else if (!b)
- ClearElement(root, "Attributes");
-
+
NormalizeWhitespace(e);
}
-
-#if !NET_1_0
- private static string MakeAttributesValueString(object v) {
- if (v == null) return "null";
- else if (v is string) return "\"" + v + "\"";
- else if (v is bool) return (bool)v ? "true" : "false";
- else if (v is Type) return "typeof(" + GetCSharpFullName ((Type)v) + ")";
- else if (v is Enum) {
- string typename = v.GetType ().FullName;
- return typename + "." + v.ToString().Replace(", ", " | " + typename + ".");
- }
- else return v.ToString();
+
+ public static string MakeAttributesValueString (object v, TypeReference valueType)
+ {
+ if (v == null)
+ return "null";
+ if (valueType.FullName == "System.Type")
+ return "typeof(" + v.ToString () + ")";
+ if (valueType.FullName == "System.String")
+ return "\"" + v.ToString () + "\"";
+ if (valueType.FullName == "System.Char")
+ return "'" + v.ToString () + "'";
+ if (v is Boolean)
+ return (bool)v ? "true" : "false";
+ TypeDefinition valueDef = valueType.Resolve ();
+ if (valueDef == null || !valueDef.IsEnum)
+ return v.ToString ();
+ string typename = GetDocTypeFullName (valueType);
+ var values = GetEnumerationValues (valueDef);
+ long c = ToInt64 (v);
+ if (values.ContainsKey (c))
+ return typename + "." + values [c];
+ if (valueDef.CustomAttributes.Any (ca => ca.AttributeType.FullName == "System.FlagsAttribute")) {
+ return string.Join (" | ",
+ (from i in values.Keys
+ where (c & i) != 0
+ select typename + "." + values [i])
+ .DefaultIfEmpty (v.ToString ()).ToArray ());
+ }
+ return "(" + GetDocTypeFullName (valueType) + ") " + v.ToString ();
+ }
+
+ private static Dictionary<long, string> GetEnumerationValues (TypeDefinition type)
+ {
+ var values = new Dictionary<long, string> ();
+ foreach (var f in
+ (from f in type.Fields
+ where !(f.IsRuntimeSpecialName || f.IsSpecialName)
+ select f)) {
+ values [ToInt64 (f.Constant)] = f.Name;
+ }
+ return values;
+ }
+
+ static long ToInt64 (object value)
+ {
+ if (value is ulong)
+ return (long) (ulong) value;
+ return Convert.ToInt64 (value);
}
-#endif
- private static void MakeParameters(XmlElement root, ParameterInfo[] parameters) {
+ private void MakeParameters (XmlElement root, IList<ParameterDefinition> parameters)
+ {
XmlElement e = WriteElement(root, "Parameters");
e.RemoveAll();
- foreach (ParameterInfo p in parameters) {
+ foreach (ParameterDefinition p in parameters) {
XmlElement pe = root.OwnerDocument.CreateElement("Parameter");
e.AppendChild(pe);
pe.SetAttribute("Name", p.Name);
pe.SetAttribute("Type", GetDocParameterType (p.ParameterType));
- if (p.ParameterType.IsByRef) {
+ if (p.ParameterType is ByReferenceType) {
if (p.IsOut) pe.SetAttribute("RefType", "out");
else pe.SetAttribute("RefType", "ref");
}
- MakeAttributes(pe, p, false);
+ MakeAttributes (pe, GetCustomAttributes (p.CustomAttributes, ""));
}
}
- private static void MakeTypeParameters(XmlElement root, Type[] typeParams)
+ private void MakeTypeParameters (XmlElement root, IList<GenericParameter> typeParams)
{
- if (typeParams == null || typeParams.Length == 0) {
+ if (typeParams == null || typeParams.Count == 0) {
XmlElement f = (XmlElement) root.SelectSingleNode ("TypeParameters");
if (f != null)
root.RemoveChild (f);
}
XmlElement e = WriteElement(root, "TypeParameters");
e.RemoveAll();
- foreach (Type t in typeParams) {
+ foreach (GenericParameter t in typeParams) {
XmlElement pe = root.OwnerDocument.CreateElement("TypeParameter");
e.AppendChild(pe);
pe.SetAttribute("Name", t.Name);
- MakeAttributes(pe, t, false);
-#if !NET_1_0
+ MakeAttributes (pe, GetCustomAttributes (t.CustomAttributes, ""));
XmlElement ce = (XmlElement) e.SelectSingleNode ("Constraints");
- GenericParameterAttributes attrs = t.GenericParameterAttributes;
- Type[] constraints = t.GetGenericParameterConstraints ();
- if (attrs == GenericParameterAttributes.None && constraints.Length == 0) {
+ IList<TypeReference> constraints = t.Constraints;
+ GenericParameterAttributes attrs = t.Attributes;
+ if (attrs == GenericParameterAttributes.NonVariant && constraints.Count == 0) {
if (ce != null)
e.RemoveChild (ce);
continue;
AppendElementText (ce, "ParameterAttribute", "NotNullableValueTypeConstraint");
if ((attrs & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
AppendElementText (ce, "ParameterAttribute", "ReferenceTypeConstraint");
- foreach (Type c in constraints) {
- AppendElementText (ce,
- c.IsInterface ? "InterfaceName" : "BaseTypeName", GetDocTypeFullName (c));
+ foreach (TypeReference c in constraints) {
+ TypeDefinition cd = c.Resolve ();
+ AppendElementText (ce,
+ (cd != null && cd.IsInterface) ? "InterfaceName" : "BaseTypeName",
+ GetDocTypeFullName (c));
}
-#endif
}
}
- private static void MakeParameters(XmlElement root, MemberInfo mi) {
- if (mi is ConstructorInfo) MakeParameters(root, ((ConstructorInfo)mi).GetParameters());
- else if (mi is MethodInfo) {
- MethodBase mb = (MethodBase) mi;
- ParameterInfo[] parameters = mb.GetParameters();
+ private void MakeParameters (XmlElement root, MemberReference mi)
+ {
+ if (mi is MethodDefinition && ((MethodDefinition) mi).IsConstructor)
+ MakeParameters (root, ((MethodDefinition)mi).Parameters);
+ else if (mi is MethodDefinition) {
+ MethodDefinition mb = (MethodDefinition) mi;
+ IList<ParameterDefinition> parameters = mb.Parameters;
MakeParameters(root, parameters);
- if (parameters.Length > 0 && DocUtils.IsExtensionMethod (mb)) {
+ if (parameters.Count > 0 && DocUtils.IsExtensionMethod (mb)) {
XmlElement p = (XmlElement) root.SelectSingleNode ("Parameters/Parameter[position()=1]");
p.SetAttribute ("RefType", "this");
}
}
- else if (mi is PropertyInfo) {
- ParameterInfo[] parameters = ((PropertyInfo)mi).GetIndexParameters();
- if (parameters.Length > 0)
+ else if (mi is PropertyDefinition) {
+ IList<ParameterDefinition> parameters = ((PropertyDefinition)mi).Parameters;
+ if (parameters.Count > 0)
MakeParameters(root, parameters);
else
return;
}
- else if (mi is FieldInfo) return;
- else if (mi is EventInfo) return;
+ else if (mi is FieldDefinition) return;
+ else if (mi is EventDefinition) return;
else throw new ArgumentException();
}
- private static string GetDocParameterType (Type type)
+ internal static string GetDocParameterType (TypeReference type)
{
return GetDocTypeFullName (type).Replace ("@", "&");
}
- private static void MakeReturnValue(XmlElement root, Type type, ICustomAttributeProvider attributes) {
+ private void MakeReturnValue (XmlElement root, TypeReference type, IList<CustomAttribute> attributes)
+ {
XmlElement e = WriteElement(root, "ReturnValue");
e.RemoveAll();
WriteElementText(e, "ReturnType", GetDocTypeFullName (type));
if (attributes != null)
- MakeAttributes(e, attributes, false);
+ MakeAttributes(e, GetCustomAttributes (attributes, ""));
}
- private static void MakeReturnValue(XmlElement root, MemberInfo mi) {
- if (mi is ConstructorInfo) return;
- else if (mi is MethodInfo) MakeReturnValue(root, ((MethodInfo)mi).ReturnType, ((MethodInfo)mi).ReturnTypeCustomAttributes);
- else if (mi is PropertyInfo) MakeReturnValue(root, ((PropertyInfo)mi).PropertyType, null);
- else if (mi is FieldInfo) MakeReturnValue(root, ((FieldInfo)mi).FieldType, null);
- else if (mi is EventInfo) MakeReturnValue(root, ((EventInfo)mi).EventHandlerType, null);
- else throw new ArgumentException(mi + " is a " + mi.GetType().FullName);
+ private void MakeReturnValue (XmlElement root, MemberReference mi)
+ {
+ if (mi is MethodDefinition && ((MethodDefinition) mi).IsConstructor)
+ return;
+ else if (mi is MethodDefinition)
+ MakeReturnValue (root, ((MethodDefinition)mi).ReturnType, ((MethodDefinition)mi).MethodReturnType.CustomAttributes);
+ else if (mi is PropertyDefinition)
+ MakeReturnValue (root, ((PropertyDefinition)mi).PropertyType, null);
+ else if (mi is FieldDefinition)
+ MakeReturnValue (root, ((FieldDefinition)mi).FieldType, null);
+ else if (mi is EventDefinition)
+ MakeReturnValue (root, ((EventDefinition)mi).EventType, null);
+ else
+ throw new ArgumentException(mi + " is a " + mi.GetType().FullName);
}
- private static XmlElement MakeMember(XmlDocument doc, DocsNodeInfo info) {
- MemberInfo mi = info.Member;
- if (mi is Type) return null;
+ private XmlElement MakeMember(XmlDocument doc, DocsNodeInfo info)
+ {
+ MemberReference mi = info.Member;
+ if (mi is TypeDefinition) return null;
- string sigs = MakeMemberSignature(mi);
+ string sigs = memberFormatters [0].GetDeclaration (mi);
if (sigs == null) return null; // not publicly visible
// no documentation for property/event accessors. Is there a better way of doing this?
info.Node = me;
UpdateMember(info);
+ if (exceptions.HasValue &&
+ (exceptions.Value & ExceptionLocations.AddedMembers) != 0)
+ UpdateExceptions (info.Node, info.Member);
if (since != null) {
XmlNode docs = me.SelectSingleNode("Docs");
return me;
}
- private static string GetMemberName (MemberInfo mi)
+ internal static string GetMemberName (MemberReference mi)
{
- MethodBase mb = mi as MethodBase;
+ MethodDefinition mb = mi as MethodDefinition;
if (mb == null) {
- PropertyInfo pi = mi as PropertyInfo;
+ PropertyDefinition pi = mi as PropertyDefinition;
if (pi == null)
return mi.Name;
return DocUtils.GetPropertyName (pi);
if (!DocUtils.IsExplicitlyImplemented (mb))
sb.Append (mi.Name);
else {
- Type iface;
- MethodInfo ifaceMethod;
+ TypeReference iface;
+ MethodReference ifaceMethod;
DocUtils.GetInfoForExplicitlyImplementedMethod (mb, out iface, out ifaceMethod);
sb.Append (GetDocTypeFullName (iface));
sb.Append ('.');
sb.Append (ifaceMethod.Name);
}
- if (DocUtils.GetContainsGenericParameters (mb)) {
- Type[] typeParams = DocUtils.GetGenericArguments (mb);
- if (typeParams.Length > 0) {
+ if (mb.IsGenericMethod ()) {
+ IList<GenericParameter> typeParams = mb.GenericParameters;
+ if (typeParams.Count > 0) {
sb.Append ("<");
sb.Append (typeParams [0].Name);
- for (int i = 1; i < typeParams.Length; ++i)
+ for (int i = 1; i < typeParams.Count; ++i)
sb.Append (",").Append (typeParams [i].Name);
sb.Append (">");
}
}
return sb.ToString ();
}
-
- private static int CountChars (string s, char c)
- {
- int count = 0;
- for (int i = 0; i < s.Length; ++i) {
- if (s [i] == c)
- ++count;
- }
- return count;
- }
-
- static bool IsDelegate(Type type) {
- return typeof(System.Delegate).IsAssignableFrom (type) && !type.IsAbstract;
- }
/// SIGNATURE GENERATION FUNCTIONS
-
- private static bool InterfaceNotFromAnother(Type i, Type[] i2) {
- foreach (Type t in i2)
- if (i != t && Array.IndexOf(t.GetInterfaces(), i) != -1)
- return false;
- return true;
- }
-
- static string MakeTypeSignature (Type type) {
- return csharpFormatter.GetDeclaration (type);
- }
-
- static string MakeMemberSignature(MemberInfo mi) {
- return csharpFullFormatter.GetDeclaration (mi);
+ internal static bool IsPrivate (MemberReference mi)
+ {
+ return memberFormatters [0].GetDeclaration (mi) == null;
}
- 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";
+ internal static string GetMemberType (MemberReference mi)
+ {
+ if (mi is MethodDefinition && ((MethodDefinition) mi).IsConstructor)
+ return "Constructor";
+ if (mi is MethodDefinition)
+ return "Method";
+ if (mi is PropertyDefinition)
+ return "Property";
+ if (mi is FieldDefinition)
+ return "Field";
+ if (mi is EventDefinition)
+ return "Event";
throw new ArgumentException();
}
- private static string GetDocTypeName (Type type)
+ private static string GetDocTypeName (TypeReference type)
{
return docTypeFormatter.GetName (type);
}
- private static string GetDocTypeFullName (Type type)
- {
- return DocTypeFullMemberFormatter.Default.GetName (type);
- }
-
- private static string GetCSharpFullName (Type type)
+ internal static string GetDocTypeFullName (TypeReference type)
{
return DocTypeFullMemberFormatter.Default.GetName (type);
}
- class DocsNodeInfo {
- public DocsNodeInfo (XmlElement node)
- {
- this.Node = node;
- }
-
- public DocsNodeInfo (XmlElement node, Type type)
- : this (node)
- {
- SetType (type);
- }
-
- public DocsNodeInfo (XmlElement node, MemberInfo member)
- : this (node)
- {
- SetMemberInfo (member);
- }
-
- public void SetType (Type type)
- {
- if (type == null)
- throw new ArgumentNullException ("type");
- GenericParameters = DocUtils.GetGenericArguments (type);
- if (type.DeclaringType != null) {
- Type[] declGenParams = DocUtils.GetGenericArguments (type.DeclaringType);
- if (declGenParams != null && GenericParameters.Length == declGenParams.Length) {
- GenericParameters = null;
- }
- else if (declGenParams != null) {
- Type[] nestedParams = new Type [GenericParameters.Length - declGenParams.Length];
- for (int i = 0; i < nestedParams.Length; ++i) {
- nestedParams [i] = GenericParameters [i+declGenParams.Length];
- }
- GenericParameters = nestedParams;
- }
- }
- if (IsDelegate(type)) {
- Parameters = type.GetMethod("Invoke").GetParameters();
- ReturnType = type.GetMethod("Invoke").ReturnType;
- }
- SetSlashDocs (type);
- }
-
- public void SetMemberInfo (MemberInfo member)
- {
- if (member == null)
- throw new ArgumentNullException ("member");
- ReturnIsReturn = true;
- AddRemarks = true;
- Member = member;
-
- if (member is MethodInfo || member is ConstructorInfo) {
- Parameters = ((MethodBase) member).GetParameters ();
- if (DocUtils.GetContainsGenericParameters ((MethodBase) member)) {
- GenericParameters = DocUtils.GetGenericArguments ((MethodBase) member);
- }
- }
- else if (member is PropertyInfo) {
- Parameters = ((PropertyInfo) member).GetIndexParameters ();
- }
-
- if (member is MethodInfo) {
- ReturnType = ((MethodInfo) member).ReturnType;
- } else if (member is PropertyInfo) {
- ReturnType = ((PropertyInfo) member).PropertyType;
- ReturnIsReturn = false;
- }
-
- // no remarks section for enum members
- if (member.DeclaringType != null && member.DeclaringType.IsEnum)
- AddRemarks = false;
- SetSlashDocs (member);
- }
-
- private void SetSlashDocs (MemberInfo member)
- {
- if (slashdocs == null)
- return;
-
- string slashdocsig = slashdocFormatter.GetDeclaration (member);
- if (slashdocsig != null)
- SlashDocs = slashdocs.SelectSingleNode ("doc/members/member[@name='" + slashdocsig + "']");
- }
-
- public Type ReturnType;
- public Type[] GenericParameters;
- public ParameterInfo[] Parameters;
- public bool ReturnIsReturn;
- public XmlElement Node;
- public bool AddRemarks = true;
- public XmlNode SlashDocs;
- public XmlReader EcmaDocs;
- public MemberInfo Member;
- }
-
- static string GetXPathForMember (DocumentationMember member)
+ internal static string GetXPathForMember (DocumentationMember member)
{
StringBuilder xpath = new StringBuilder ();
xpath.Append ("//Members/Member[@MemberName=\"")
{
StringBuilder xpath = new StringBuilder ();
xpath.Append ("//Type[@FullName=\"")
- .Append (SelectSingleNode (member, "../../@FullName").Value)
+ .Append (member.SelectSingleNode ("../../@FullName").Value)
.Append ("\"]/");
xpath.Append ("Members/Member[@MemberName=\"")
- .Append (SelectSingleNode (member, "@MemberName").Value)
+ .Append (member.SelectSingleNode ("@MemberName").Value)
.Append ("\"]");
XPathNodeIterator parameters = member.Select ("Parameters/Parameter");
if (parameters.Count > 0) {
return xpath.ToString ();
}
- public static string GetXPathForMember (MemberInfo member)
+ public static string GetXPathForMember (MemberReference member)
{
StringBuilder xpath = new StringBuilder ();
xpath.Append ("//Type[@FullName=\"")
.Append (GetMemberName (member))
.Append ("\"]");
- ParameterInfo[] parameters = null;
- if (member is MethodBase)
- parameters = ((MethodBase) member).GetParameters ();
- else if (member is PropertyInfo) {
- parameters = ((PropertyInfo) member).GetIndexParameters ();
+ IList<ParameterDefinition> parameters = null;
+ if (member is MethodDefinition)
+ parameters = ((MethodDefinition) member).Parameters;
+ else if (member is PropertyDefinition) {
+ parameters = ((PropertyDefinition) member).Parameters;
}
- if (parameters != null && parameters.Length > 0) {
+ if (parameters != null && parameters.Count > 0) {
xpath.Append ("/Parameters[count(Parameter) = ")
- .Append (parameters.Length);
- for (int i = 0; i < parameters.Length; ++i) {
+ .Append (parameters.Count);
+ for (int i = 0; i < parameters.Count; ++i) {
xpath.Append (" and Parameter [").Append (i+1).Append ("]/@Type=\"");
xpath.Append (GetDocParameterType (parameters [i].ParameterType));
xpath.Append ("\"");
}
}
-static class DocUtils {
- public static bool GetContainsGenericParameters (Type type)
+static class CecilExtensions {
+ public static string GetDeclaringType(this CustomAttribute attribute)
{
-#if NET_1_0
- return false;
-#else
- return type.ContainsGenericParameters;
-#endif
+ return attribute.Constructor.DeclaringType.FullName;
}
- public static bool GetContainsGenericParameters (MethodBase mb)
+ public static IEnumerable<MemberReference> GetMembers (this TypeDefinition type)
{
-#if NET_1_0
- return false;
-#else
- return mb.ContainsGenericParameters;
-#endif
+ foreach (var c in type.Methods.Where (m => m.IsConstructor))
+ yield return (MemberReference) c;
+ foreach (var e in type.Events)
+ yield return (MemberReference) e;
+ foreach (var f in type.Fields)
+ yield return (MemberReference) f;
+ foreach (var m in type.Methods.Where (m => !m.IsConstructor))
+ yield return (MemberReference) m;
+ foreach (var t in type.NestedTypes)
+ yield return (MemberReference) t;
+ foreach (var p in type.Properties)
+ yield return (MemberReference) p;
}
- public static Type[] GetGenericArguments (Type type)
+ public static IEnumerable<MemberReference> GetMembers (this TypeDefinition type, string member)
{
-#if NET_1_0
- return new Type [0];
-#else
- return type.GetGenericArguments ();
-#endif
+ return GetMembers (type).Where (m => m.Name == member);
}
- public static Type[] GetGenericArguments (MethodBase mb)
+ public static MemberReference GetMember (this TypeDefinition type, string member)
{
-#if NET_1_0
- return new Type [0];
-#else
- return mb.GetGenericArguments ();
-#endif
+ return GetMembers (type, member).EnsureZeroOrOne ();
}
- public static Type GetGenericTypeDefinition (Type type)
+ static T EnsureZeroOrOne<T> (this IEnumerable<T> source)
{
-#if NET_1_0
- return null;
-#else
- return type.GetGenericTypeDefinition ();
-#endif
+ if (source.Count () > 1)
+ throw new InvalidOperationException ("too many matches");
+ return source.FirstOrDefault ();
}
- public static Type[] GetGenericParameterConstraints (Type type)
+ public static MethodDefinition GetMethod (this TypeDefinition type, string method)
{
-#if NET_1_0
- return null;
-#else
- return type.GetGenericParameterConstraints ();
-#endif
+ return type.Methods
+ .Where (m => m.Name == method)
+ .EnsureZeroOrOne ();
}
- public static bool IsGenericType (Type type)
+ public static IEnumerable<MemberReference> GetDefaultMembers (this TypeReference type)
{
-#if NET_1_0
- return false;
-#else
- return type.IsGenericType;
-#endif
+ TypeDefinition def = type as TypeDefinition;
+ if (def == null)
+ return new MemberReference [0];
+ CustomAttribute defMemberAttr = def.CustomAttributes
+ .FirstOrDefault (c => c.AttributeType.FullName == "System.Reflection.DefaultMemberAttribute");
+ if (defMemberAttr == null)
+ return new MemberReference [0];
+ string name = (string) defMemberAttr.ConstructorArguments [0].Value;
+ return def.Properties
+ .Where (p => p.Name == name)
+ .Select (p => (MemberReference) p);
}
- public static bool IsGenericParameter (Type type)
+ public static IEnumerable<TypeDefinition> GetTypes (this AssemblyDefinition assembly)
{
-#if NET_1_0
- return false;
-#else
- return type.IsGenericParameter;
-#endif
+ return assembly.Modules.SelectMany (md => md.GetAllTypes ());
+ }
+
+ public static TypeDefinition GetType (this AssemblyDefinition assembly, string type)
+ {
+ return GetTypes (assembly)
+ .Where (td => td.FullName == type)
+ .EnsureZeroOrOne ();
+ }
+
+ public static bool IsGenericType (this TypeReference type)
+ {
+ return type.GenericParameters.Count > 0;
+ }
+
+ public static bool IsGenericMethod (this MethodReference method)
+ {
+ return method.GenericParameters.Count > 0;
+ }
+
+ public static MemberReference Resolve (this MemberReference member)
+ {
+ FieldReference fr = member as FieldReference;
+ if (fr != null)
+ return fr.Resolve ();
+ MethodReference mr = member as MethodReference;
+ if (mr != null)
+ return mr.Resolve ();
+ TypeReference tr = member as TypeReference;
+ if (tr != null)
+ return tr.Resolve ();
+ PropertyReference pr = member as PropertyReference;
+ if (pr != null)
+ return pr;
+ EventReference er = member as EventReference;
+ if (er != null)
+ return er;
+ throw new NotSupportedException ("Cannot find definition for " + member.ToString ());
+ }
+
+ public static TypeReference GetUnderlyingType (this TypeDefinition type)
+ {
+ if (!type.IsEnum)
+ return type;
+ return type.Fields.First (f => f.Name == "value__").FieldType;
}
- public static bool IsExplicitlyImplemented (MethodBase method)
+ public static IEnumerable<TypeDefinition> GetAllTypes (this ModuleDefinition self)
+ {
+ return self.Types.SelectMany (t => t.GetAllTypes ());
+ }
+
+ static IEnumerable<TypeDefinition> GetAllTypes (this TypeDefinition self)
+ {
+ yield return self;
+
+ if (!self.HasNestedTypes)
+ yield break;
+
+ foreach (var type in self.NestedTypes.SelectMany (t => t.GetAllTypes ()))
+ yield return type;
+ }
+}
+
+static class DocUtils {
+ public static bool IsExplicitlyImplemented (MethodDefinition method)
{
return method.IsPrivate && method.IsFinal && method.IsVirtual;
}
}
public static void GetInfoForExplicitlyImplementedMethod (
- MethodBase method, out Type iface, out MethodInfo ifaceMethod)
- {
- Type declType = method.DeclaringType;
- foreach (Type declIface in declType.GetInterfaces ()) {
- InterfaceMapping map = declType.GetInterfaceMap (declIface);
- for (int i = 0; i < map.TargetMethods.Length; ++i)
- if (method == map.TargetMethods [i]) {
- iface = map.InterfaceType;
- ifaceMethod = map.InterfaceMethods [i];
- return;
- }
- }
- throw new InvalidOperationException ("Could not determine interface type for explicitly-implemented interface member " + method.Name);
- }
-
- public static string[] ToStringArray (StringList list)
+ MethodDefinition method, out TypeReference iface, out MethodReference ifaceMethod)
{
-#if NET_1_0
- return (string[]) list.ToArray (typeof(string));
-#else
- return list.ToArray ();
-#endif
+ iface = null;
+ ifaceMethod = null;
+ if (method.Overrides.Count != 1)
+ throw new InvalidOperationException ("Could not determine interface type for explicitly-implemented interface member " + method.Name);
+ iface = method.Overrides [0].DeclaringType;
+ ifaceMethod = method.Overrides [0];
}
- public static string GetPropertyName (PropertyInfo pi)
+ public static string GetPropertyName (PropertyDefinition pi)
{
// Issue: (g)mcs-generated assemblies that explicitly implement
// properties don't specify the full namespace, just the
// TypeName.Property; .NET uses Full.Namespace.TypeName.Property.
- MethodInfo method = pi.GetGetMethod (true);
+ MethodDefinition method = pi.GetMethod;
if (method == null)
- method = pi.GetSetMethod (true);
+ method = pi.SetMethod;
if (!IsExplicitlyImplemented (method))
return pi.Name;
// Need to determine appropriate namespace for this member.
- Type iface;
- MethodInfo ifaceMethod;
+ TypeReference iface;
+ MethodReference ifaceMethod;
GetInfoForExplicitlyImplementedMethod (method, out iface, out ifaceMethod);
return string.Join (".", new string[]{
DocTypeFullMemberFormatter.Default.GetName (iface),
GetMember (pi.Name)});
}
+ public static string GetNamespace (TypeReference type)
+ {
+ if (type.GetElementType ().IsNested)
+ type = type.GetElementType ();
+ while (type != null && type.IsNested)
+ type = type.DeclaringType;
+ if (type == null)
+ return string.Empty;
+ return type.Namespace;
+ }
+
public static string PathCombine (string dir, string path)
{
if (dir == null)
return Path.Combine (dir, path);
}
- public static bool IsExtensionMethod (MethodBase method)
+ public static bool IsExtensionMethod (MethodDefinition method)
{
-#if NET_1_0
- return false;
-#else
- return
- method.GetCustomAttributes (
- typeof(System.Runtime.CompilerServices.ExtensionAttribute),
- false).Length != 0 &&
- method.DeclaringType.GetCustomAttributes (
- typeof(System.Runtime.CompilerServices.ExtensionAttribute),
- false).Length != 0;
-#endif
+ return
+ method.CustomAttributes
+ .Any (m => m.AttributeType.FullName == "System.Runtime.CompilerServices.ExtensionAttribute")
+ && method.DeclaringType.CustomAttributes
+ .Any (m => m.AttributeType.FullName == "System.Runtime.CompilerServices.ExtensionAttribute");
}
-}
-class DocumentationMember {
- public StringToStringMap MemberSignatures = new StringToStringMap ();
- public string ReturnType;
- public StringList Parameters;
- public string MemberName;
- public string MemberType;
+ public static bool IsDelegate (TypeDefinition type)
+ {
+ TypeReference baseRef = type.BaseType;
+ if (baseRef == null)
+ return false;
+ return !type.IsAbstract && baseRef.FullName == "System.Delegate" || // FIXME
+ baseRef.FullName == "System.MulticastDelegate";
+ }
- public DocumentationMember (XmlReader reader)
+ public static List<TypeReference> GetDeclaringTypes (TypeReference type)
{
- MemberName = reader.GetAttribute ("MemberName");
- int depth = reader.Depth;
- bool go = true;
- StringList p = new StringList ();
- do {
- if (reader.NodeType != XmlNodeType.Element)
- continue;
- switch (reader.Name) {
- case "MemberSignature":
- MemberSignatures [reader.GetAttribute ("Language")] = reader.GetAttribute ("Value");
- break;
- case "MemberType":
- MemberType = reader.ReadElementString ();
- break;
- case "ReturnType":
- if (reader.Depth == depth + 2)
+ List<TypeReference> decls = new List<TypeReference> ();
+ decls.Add (type);
+ while (type.DeclaringType != null) {
+ decls.Add (type.DeclaringType);
+ type = type.DeclaringType;
+ }
+ decls.Reverse ();
+ return decls;
+ }
+
+ public static int GetGenericArgumentCount (TypeReference type)
+ {
+ GenericInstanceType inst = type as GenericInstanceType;
+ return inst != null
+ ? inst.GenericArguments.Count
+ : type.GenericParameters.Count;
+ }
+
+ public static IEnumerable<TypeReference> GetUserImplementedInterfaces (TypeDefinition type)
+ {
+ HashSet<string> inheritedInterfaces = GetInheritedInterfaces (type);
+ List<TypeReference> userInterfaces = new List<TypeReference> ();
+ foreach (TypeReference iface in type.Interfaces) {
+ TypeReference lookup = iface.Resolve () ?? iface;
+ if (!inheritedInterfaces.Contains (GetQualifiedTypeName (lookup)))
+ userInterfaces.Add (iface);
+ }
+ return userInterfaces;
+ }
+
+ private static string GetQualifiedTypeName (TypeReference type)
+ {
+ return "[" + type.Scope.Name + "]" + type.FullName;
+ }
+
+ private static HashSet<string> GetInheritedInterfaces (TypeDefinition type)
+ {
+ HashSet<string> inheritedInterfaces = new HashSet<string> ();
+ Action<TypeDefinition> a = null;
+ a = t => {
+ if (t == null) return;
+ foreach (TypeReference r in t.Interfaces) {
+ inheritedInterfaces.Add (GetQualifiedTypeName (r));
+ a (r.Resolve ());
+ }
+ };
+ TypeReference baseRef = type.BaseType;
+ while (baseRef != null) {
+ TypeDefinition baseDef = baseRef.Resolve ();
+ if (baseDef != null) {
+ a (baseDef);
+ baseRef = baseDef.BaseType;
+ }
+ else
+ baseRef = null;
+ }
+ foreach (TypeReference r in type.Interfaces)
+ a (r.Resolve ());
+ return inheritedInterfaces;
+ }
+}
+
+class DocsNodeInfo {
+ public DocsNodeInfo (XmlElement node)
+ {
+ this.Node = node;
+ }
+
+ public DocsNodeInfo (XmlElement node, TypeDefinition type)
+ : this (node)
+ {
+ SetType (type);
+ }
+
+ public DocsNodeInfo (XmlElement node, MemberReference member)
+ : this (node)
+ {
+ SetMemberInfo (member);
+ }
+
+ void SetType (TypeDefinition type)
+ {
+ if (type == null)
+ throw new ArgumentNullException ("type");
+ Type = type;
+ GenericParameters = new List<GenericParameter> (type.GenericParameters);
+ List<TypeReference> declTypes = DocUtils.GetDeclaringTypes (type);
+ int maxGenArgs = DocUtils.GetGenericArgumentCount (type);
+ for (int i = 0; i < declTypes.Count - 1; ++i) {
+ int remove = System.Math.Min (maxGenArgs,
+ DocUtils.GetGenericArgumentCount (declTypes [i]));
+ maxGenArgs -= remove;
+ while (remove-- > 0)
+ GenericParameters.RemoveAt (0);
+ }
+ if (DocUtils.IsDelegate (type)) {
+ Parameters = type.GetMethod("Invoke").Parameters;
+ ReturnType = type.GetMethod("Invoke").ReturnType;
+ ReturnIsReturn = true;
+ }
+ }
+
+ void SetMemberInfo (MemberReference member)
+ {
+ if (member == null)
+ throw new ArgumentNullException ("member");
+ ReturnIsReturn = true;
+ AddRemarks = true;
+ Member = member;
+
+ if (member is MethodReference ) {
+ MethodReference mr = (MethodReference) member;
+ Parameters = mr.Parameters;
+ if (mr.IsGenericMethod ()) {
+ GenericParameters = new List<GenericParameter> (mr.GenericParameters);
+ }
+ }
+ else if (member is PropertyDefinition) {
+ Parameters = ((PropertyDefinition) member).Parameters;
+ }
+
+ if (member is MethodDefinition) {
+ ReturnType = ((MethodDefinition) member).ReturnType;
+ } else if (member is PropertyDefinition) {
+ ReturnType = ((PropertyDefinition) member).PropertyType;
+ ReturnIsReturn = false;
+ }
+
+ // no remarks section for enum members
+ if (member.DeclaringType != null && ((TypeDefinition) member.DeclaringType).IsEnum)
+ AddRemarks = false;
+ }
+
+ public TypeReference ReturnType;
+ public List<GenericParameter> GenericParameters;
+ public IList<ParameterDefinition> Parameters;
+ public bool ReturnIsReturn;
+ public XmlElement Node;
+ public bool AddRemarks = true;
+ public MemberReference Member;
+ public TypeDefinition Type;
+}
+
+class DocumentationEnumerator {
+
+ public virtual IEnumerable<TypeDefinition> GetDocumentationTypes (AssemblyDefinition assembly, List<string> forTypes)
+ {
+ return GetDocumentationTypes (assembly, forTypes, null);
+ }
+
+ protected IEnumerable<TypeDefinition> GetDocumentationTypes (AssemblyDefinition assembly, List<string> forTypes, HashSet<string> seen)
+ {
+ foreach (TypeDefinition type in assembly.GetTypes()) {
+ if (forTypes != null && forTypes.BinarySearch (type.FullName) < 0)
+ continue;
+ if (seen != null && seen.Contains (type.FullName))
+ continue;
+ yield return type;
+ foreach (TypeDefinition nested in type.NestedTypes)
+ yield return nested;
+ }
+ }
+
+ public virtual IEnumerable<DocsNodeInfo> GetDocumentationMembers (XmlDocument basefile, TypeDefinition type)
+ {
+ foreach (XmlElement oldmember in basefile.SelectNodes("Type/Members/Member")) {
+ if (oldmember.GetAttribute ("__monodocer-seen__") == "true") {
+ oldmember.RemoveAttribute ("__monodocer-seen__");
+ continue;
+ }
+ MemberReference m = GetMember (type, new DocumentationMember (oldmember));
+ if (m == null) {
+ yield return new DocsNodeInfo (oldmember);
+ }
+ else {
+ yield return new DocsNodeInfo (oldmember, m);
+ }
+ }
+ }
+
+ protected static MemberReference GetMember (TypeDefinition type, DocumentationMember member)
+ {
+ string membertype = member.MemberType;
+
+ string returntype = member.ReturnType;
+
+ string docName = member.MemberName;
+ string[] docTypeParams = GetTypeParameters (docName);
+
+ // Loop through all members in this type with the same name
+ foreach (MemberReference mi in GetReflectionMembers (type, docName)) {
+ if (mi is TypeDefinition) continue;
+ if (MDocUpdater.GetMemberType(mi) != membertype) continue;
+
+ if (MDocUpdater.IsPrivate (mi))
+ continue;
+
+ IList<ParameterDefinition> pis = null;
+ string[] typeParams = null;
+ if (mi is MethodDefinition) {
+ MethodDefinition mb = (MethodDefinition) mi;
+ pis = mb.Parameters;
+ if (docTypeParams != null && mb.IsGenericMethod ()) {
+ IList<GenericParameter> args = mb.GenericParameters;
+ if (args.Count == docTypeParams.Length) {
+ typeParams = args.Select (p => p.Name).ToArray ();
+ }
+ }
+ }
+ else if (mi is PropertyDefinition)
+ pis = ((PropertyDefinition)mi).Parameters;
+
+ int mcount = member.Parameters == null ? 0 : member.Parameters.Count;
+ int pcount = pis == null ? 0 : pis.Count;
+ if (mcount != pcount)
+ continue;
+
+ MethodDefinition mDef = mi as MethodDefinition;
+ if (mDef != null && !mDef.IsConstructor) {
+ // Casting operators can overload based on return type.
+ if (returntype != GetReplacedString (
+ MDocUpdater.GetDocTypeFullName (((MethodDefinition)mi).ReturnType),
+ typeParams, docTypeParams)) {
+ continue;
+ }
+ }
+
+ if (pcount == 0)
+ return mi;
+ bool good = true;
+ for (int i = 0; i < pis.Count; i++) {
+ string paramType = GetReplacedString (
+ MDocUpdater.GetDocParameterType (pis [i].ParameterType),
+ typeParams, docTypeParams);
+ if (paramType != (string) member.Parameters [i]) {
+ good = false;
+ break;
+ }
+ }
+ if (!good) continue;
+
+ return mi;
+ }
+
+ return null;
+ }
+
+ static string[] GetTypeParameters (string docName)
+ {
+ if (docName [docName.Length-1] != '>')
+ return null;
+ StringList types = new StringList ();
+ int endToken = docName.Length-2;
+ int i = docName.Length-2;
+ do {
+ if (docName [i] == ',' || docName [i] == '<') {
+ types.Add (docName.Substring (i + 1, endToken - i));
+ endToken = i-1;
+ }
+ if (docName [i] == '<')
+ break;
+ } while (--i >= 0);
+
+ types.Reverse ();
+ return types.ToArray ();
+ }
+
+ protected static IEnumerable<MemberReference> GetReflectionMembers (TypeDefinition type, string docName)
+ {
+ // need to worry about 4 forms of //@MemberName values:
+ // 1. "Normal" (non-generic) member names: GetEnumerator
+ // - Lookup as-is.
+ // 2. Explicitly-implemented interface member names: System.Collections.IEnumerable.Current
+ // - try as-is, and try type.member (due to "kludge" for property
+ // support.
+ // 3. "Normal" Generic member names: Sort<T> (CSC)
+ // - need to remove generic parameters --> "Sort"
+ // 4. Explicitly-implemented interface members for generic interfaces:
+ // -- System.Collections.Generic.IEnumerable<T>.Current
+ // - Try as-is, and try type.member, *keeping* the generic parameters.
+ // --> System.Collections.Generic.IEnumerable<T>.Current, IEnumerable<T>.Current
+ // 5. As of 2008-01-02, gmcs will do e.g. 'IFoo`1[A].Method' instead of
+ // 'IFoo<A>.Method' for explicitly implemented methods; don't interpret
+ // this as (1) or (2).
+ if (docName.IndexOf ('<') == -1 && docName.IndexOf ('[') == -1) {
+ // Cases 1 & 2
+ foreach (MemberReference mi in type.GetMembers (docName))
+ yield return mi;
+ if (CountChars (docName, '.') > 0)
+ // might be a property; try only type.member instead of
+ // namespace.type.member.
+ foreach (MemberReference mi in
+ type.GetMembers (DocUtils.GetTypeDotMember (docName)))
+ yield return mi;
+ yield break;
+ }
+ // cases 3 & 4
+ int numLt = 0;
+ int numDot = 0;
+ int startLt, startType, startMethod;
+ startLt = startType = startMethod = -1;
+ for (int i = 0; i < docName.Length; ++i) {
+ switch (docName [i]) {
+ case '<':
+ if (numLt == 0) {
+ startLt = i;
+ }
+ ++numLt;
+ break;
+ case '>':
+ --numLt;
+ if (numLt == 0 && (i + 1) < docName.Length)
+ // there's another character in docName, so this <...> sequence is
+ // probably part of a generic type -- case 4.
+ startLt = -1;
+ break;
+ case '.':
+ startType = startMethod;
+ startMethod = i;
+ ++numDot;
+ break;
+ }
+ }
+ string refName = startLt == -1 ? docName : docName.Substring (0, startLt);
+ // case 3
+ foreach (MemberReference mi in type.GetMembers (refName))
+ yield return mi;
+
+ // case 4
+ foreach (MemberReference mi in type.GetMembers (refName.Substring (startType + 1)))
+ yield return mi;
+
+ // If we _still_ haven't found it, we've hit another generic naming issue:
+ // post Mono 1.1.18, gmcs generates [[FQTN]] instead of <TypeName> for
+ // explicitly-implemented METHOD names (not properties), e.g.
+ // "System.Collections.Generic.IEnumerable`1[[Foo, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]].GetEnumerator"
+ // instead of "System.Collections.Generic.IEnumerable<Foo>.GetEnumerator",
+ // which the XML docs will contain.
+ //
+ // Alas, we can't derive the Mono name from docName, so we need to iterate
+ // over all member names, convert them into CSC format, and compare... :-(
+ if (numDot == 0)
+ yield break;
+ foreach (MemberReference mi in type.GetMembers ()) {
+ if (MDocUpdater.GetMemberName (mi) == docName)
+ yield return mi;
+ }
+ }
+
+ static string GetReplacedString (string typeName, string[] from, string[] to)
+ {
+ if (from == null)
+ return typeName;
+ for (int i = 0; i < from.Length; ++i)
+ typeName = typeName.Replace (from [i], to [i]);
+ return typeName;
+ }
+
+ private static int CountChars (string s, char c)
+ {
+ int count = 0;
+ for (int i = 0; i < s.Length; ++i) {
+ if (s [i] == c)
+ ++count;
+ }
+ return count;
+ }
+}
+
+class EcmaDocumentationEnumerator : DocumentationEnumerator {
+
+ XmlReader ecmadocs;
+ MDocUpdater app;
+
+ public EcmaDocumentationEnumerator (MDocUpdater app, XmlReader ecmaDocs)
+ {
+ this.app = app;
+ this.ecmadocs = ecmaDocs;
+ }
+
+ public override IEnumerable<TypeDefinition> GetDocumentationTypes (AssemblyDefinition assembly, List<string> forTypes)
+ {
+ HashSet<string> seen = new HashSet<string> ();
+ return GetDocumentationTypes (assembly, forTypes, seen)
+ .Concat (base.GetDocumentationTypes (assembly, forTypes, seen));
+ }
+
+ new IEnumerable<TypeDefinition> GetDocumentationTypes (AssemblyDefinition assembly, List<string> forTypes, HashSet<string> seen)
+ {
+ int typeDepth = -1;
+ while (ecmadocs.Read ()) {
+ switch (ecmadocs.Name) {
+ case "Type": {
+ if (typeDepth == -1)
+ typeDepth = ecmadocs.Depth;
+ if (ecmadocs.NodeType != XmlNodeType.Element)
+ continue;
+ if (typeDepth != ecmadocs.Depth) // nested <TypeDefinition/> element?
+ continue;
+ string typename = ecmadocs.GetAttribute ("FullName");
+ string typename2 = MDocUpdater.GetTypeFileName (typename);
+ if (forTypes != null &&
+ forTypes.BinarySearch (typename) < 0 &&
+ typename != typename2 &&
+ forTypes.BinarySearch (typename2) < 0)
+ continue;
+ TypeDefinition t;
+ if ((t = assembly.GetType (typename)) == null &&
+ (t = assembly.GetType (typename2)) == null)
+ continue;
+ seen.Add (typename);
+ if (typename != typename2)
+ seen.Add (typename2);
+ Console.WriteLine (" Import: {0}", t.FullName);
+ if (ecmadocs.Name != "Docs") {
+ int depth = ecmadocs.Depth;
+ while (ecmadocs.Read ()) {
+ if (ecmadocs.Name == "Docs" && ecmadocs.Depth == depth + 1)
+ break;
+ }
+ }
+ if (!ecmadocs.IsStartElement ("Docs"))
+ throw new InvalidOperationException ("Found " + ecmadocs.Name + "; expecting <Docs/>!");
+ yield return t;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ public override IEnumerable<DocsNodeInfo> GetDocumentationMembers (XmlDocument basefile, TypeDefinition type)
+ {
+ return GetMembers (basefile, type)
+ .Concat (base.GetDocumentationMembers (basefile, type));
+ }
+
+ private IEnumerable<DocsNodeInfo> GetMembers (XmlDocument basefile, TypeDefinition type)
+ {
+ while (ecmadocs.Name != "Members" && ecmadocs.Read ()) {
+ // do nothing
+ }
+ if (ecmadocs.IsEmptyElement)
+ yield break;
+
+ int membersDepth = ecmadocs.Depth;
+ bool go = true;
+ while (go && ecmadocs.Read ()) {
+ switch (ecmadocs.Name) {
+ case "Member": {
+ if (membersDepth != ecmadocs.Depth - 1 || ecmadocs.NodeType != XmlNodeType.Element)
+ continue;
+ DocumentationMember dm = new DocumentationMember (ecmadocs);
+ string xp = MDocUpdater.GetXPathForMember (dm);
+ XmlElement oldmember = (XmlElement) basefile.SelectSingleNode (xp);
+ MemberReference m;
+ if (oldmember == null) {
+ m = GetMember (type, dm);
+ if (m == null) {
+ app.Warning ("Could not import ECMA docs for `{0}'s `{1}': Member not found.",
+ type.FullName, dm.MemberSignatures ["C#"]);
+ // SelectSingleNode (ecmaDocsMember, "MemberSignature[@Language=\"C#\"]/@Value").Value);
+ continue;
+ }
+ // oldmember lookup may have failed due to type parameter renames.
+ // Try again.
+ oldmember = (XmlElement) basefile.SelectSingleNode (MDocUpdater.GetXPathForMember (m));
+ if (oldmember == null) {
+ XmlElement members = MDocUpdater.WriteElement (basefile.DocumentElement, "Members");
+ oldmember = basefile.CreateElement ("Member");
+ oldmember.SetAttribute ("MemberName", dm.MemberName);
+ members.AppendChild (oldmember);
+ foreach (string key in MDocUpdater.Sort (dm.MemberSignatures.Keys)) {
+ XmlElement ms = basefile.CreateElement ("MemberSignature");
+ ms.SetAttribute ("Language", key);
+ ms.SetAttribute ("Value", (string) dm.MemberSignatures [key]);
+ oldmember.AppendChild (ms);
+ }
+ oldmember.SetAttribute ("__monodocer-seen__", "true");
+ Console.WriteLine ("Member Added: {0}", oldmember.SelectSingleNode("MemberSignature[@Language='C#']/@Value").InnerText);
+ app.additions++;
+ }
+ }
+ else {
+ m = GetMember (type, new DocumentationMember (oldmember));
+ if (m == null) {
+ app.Warning ("Could not import ECMA docs for `{0}'s `{1}': Member not found.",
+ type.FullName, dm.MemberSignatures ["C#"]);
+ continue;
+ }
+ oldmember.SetAttribute ("__monodocer-seen__", "true");
+ }
+ DocsNodeInfo node = new DocsNodeInfo (oldmember, m);
+ if (ecmadocs.Name != "Docs")
+ throw new InvalidOperationException ("Found " + ecmadocs.Name + "; expected <Docs/>!");
+ yield return node;
+ break;
+ }
+ case "Members":
+ if (membersDepth == ecmadocs.Depth && ecmadocs.NodeType == XmlNodeType.EndElement) {
+ go = false;
+ }
+ break;
+ }
+ }
+ }
+}
+
+abstract class DocumentationImporter {
+
+ public abstract void ImportDocumentation (DocsNodeInfo info);
+}
+
+class MsxdocDocumentationImporter : DocumentationImporter {
+
+ XmlDocument slashdocs;
+
+ public MsxdocDocumentationImporter (string file)
+ {
+ var xml = File.ReadAllText (file);
+
+ // Ensure Unix line endings
+ xml = xml.Replace ("\r", "");
+
+ slashdocs = new XmlDocument();
+ slashdocs.LoadXml (xml);
+ }
+
+ public override void ImportDocumentation (DocsNodeInfo info)
+ {
+ XmlNode elem = GetDocs (info.Member ?? info.Type);
+
+ if (elem == null)
+ return;
+
+ XmlElement e = info.Node;
+
+ if (elem.SelectSingleNode("summary") != null)
+ MDocUpdater.ClearElement(e, "summary");
+ if (elem.SelectSingleNode("remarks") != null)
+ MDocUpdater.ClearElement(e, "remarks");
+ if (elem.SelectSingleNode ("value") != null || elem.SelectSingleNode ("returns") != null) {
+ MDocUpdater.ClearElement(e, "value");
+ MDocUpdater.ClearElement(e, "returns");
+ }
+
+ foreach (XmlNode child in elem.ChildNodes) {
+ switch (child.Name) {
+ case "param":
+ case "typeparam": {
+ XmlAttribute name = child.Attributes ["name"];
+ if (name == null)
+ break;
+ XmlElement p2 = (XmlElement) e.SelectSingleNode (child.Name + "[@name='" + name.Value + "']");
+ if (p2 != null)
+ p2.InnerXml = child.InnerXml;
+ break;
+ }
+ // Occasionally XML documentation will use <returns/> on
+ // properties, so let's try to normalize things.
+ case "value":
+ case "returns": {
+ XmlElement v = e.OwnerDocument.CreateElement (info.ReturnIsReturn ? "returns" : "value");
+ v.InnerXml = child.InnerXml;
+ e.AppendChild (v);
+ break;
+ }
+ case "altmember":
+ case "exception":
+ case "permission": {
+ XmlAttribute cref = child.Attributes ["cref"] ?? child.Attributes ["name"];
+ if (cref == null)
+ break;
+ XmlElement a = (XmlElement) e.SelectSingleNode (child.Name + "[@cref='" + cref.Value + "']");
+ if (a == null) {
+ a = e.OwnerDocument.CreateElement (child.Name);
+ a.SetAttribute ("cref", child.Attributes ["cref"].Value);
+ e.AppendChild (a);
+ }
+ a.InnerXml = child.InnerXml;
+ break;
+ }
+ case "seealso": {
+ XmlAttribute cref = child.Attributes ["cref"];
+ if (cref == null)
+ break;
+ XmlElement a = (XmlElement) e.SelectSingleNode ("altmember[@cref='" + cref.Value + "']");
+ if (a == null) {
+ a = e.OwnerDocument.CreateElement ("altmember");
+ a.SetAttribute ("cref", child.Attributes ["cref"].Value);
+ e.AppendChild (a);
+ }
+ break;
+ }
+ default: {
+ bool add = true;
+ if (child.NodeType == XmlNodeType.Element &&
+ e.SelectNodes (child.Name).Cast<XmlElement>().Any (n => n.OuterXml == child.OuterXml))
+ add = false;
+ if (add)
+ MDocUpdater.CopyNode (child, e);
+ break;
+ }
+ }
+ }
+ }
+
+ private XmlNode GetDocs (MemberReference member)
+ {
+ string slashdocsig = MDocUpdater.slashdocFormatter.GetDeclaration (member);
+ if (slashdocsig != null)
+ return slashdocs.SelectSingleNode ("doc/members/member[@name='" + slashdocsig + "']");
+ return null;
+ }
+}
+
+class EcmaDocumentationImporter : DocumentationImporter {
+
+ XmlReader ecmadocs;
+
+ public EcmaDocumentationImporter (XmlReader ecmaDocs)
+ {
+ this.ecmadocs = ecmaDocs;
+ }
+
+ public override void ImportDocumentation (DocsNodeInfo info)
+ {
+ if (!ecmadocs.IsStartElement ("Docs")) {
+ return;
+ }
+
+ XmlElement e = info.Node;
+
+ int depth = ecmadocs.Depth;
+ ecmadocs.ReadStartElement ("Docs");
+ while (ecmadocs.Read ()) {
+ if (ecmadocs.Name == "Docs") {
+ if (ecmadocs.Depth == depth && ecmadocs.NodeType == XmlNodeType.EndElement)
+ break;
+ else
+ throw new InvalidOperationException ("Skipped past current <Docs/> element!");
+ }
+ if (!ecmadocs.IsStartElement ())
+ continue;
+ switch (ecmadocs.Name) {
+ case "param":
+ case "typeparam": {
+ string name = ecmadocs.GetAttribute ("name");
+ if (name == null)
+ break;
+ XmlNode doc = e.SelectSingleNode (
+ ecmadocs.Name + "[@name='" + name + "']");
+ string value = ecmadocs.ReadInnerXml ();
+ if (doc != null)
+ doc.InnerXml = value.Replace ("\r", "");
+ break;
+ }
+ case "altmember":
+ case "exception":
+ case "permission":
+ case "seealso": {
+ string name = ecmadocs.Name;
+ string cref = ecmadocs.GetAttribute ("cref");
+ if (cref == null)
+ break;
+ XmlNode doc = e.SelectSingleNode (
+ ecmadocs.Name + "[@cref='" + cref + "']");
+ string value = ecmadocs.ReadInnerXml ().Replace ("\r", "");
+ if (doc != null)
+ doc.InnerXml = value;
+ else {
+ XmlElement n = e.OwnerDocument.CreateElement (name);
+ n.SetAttribute ("cref", cref);
+ n.InnerXml = value;
+ e.AppendChild (n);
+ }
+ break;
+ }
+ default: {
+ string name = ecmadocs.Name;
+ string xpath = ecmadocs.Name;
+ StringList attributes = new StringList (ecmadocs.AttributeCount);
+ if (ecmadocs.MoveToFirstAttribute ()) {
+ do {
+ attributes.Add ("@" + ecmadocs.Name + "=\"" + ecmadocs.Value + "\"");
+ } while (ecmadocs.MoveToNextAttribute ());
+ ecmadocs.MoveToContent ();
+ }
+ if (attributes.Count > 0) {
+ xpath += "[" + string.Join (" and ", attributes.ToArray ()) + "]";
+ }
+ XmlNode doc = e.SelectSingleNode (xpath);
+ string value = ecmadocs.ReadInnerXml ().Replace ("\r", "");
+ if (doc != null) {
+ doc.InnerXml = value;
+ }
+ else {
+ XmlElement n = e.OwnerDocument.CreateElement (name);
+ n.InnerXml = value;
+ foreach (string a in attributes) {
+ int eq = a.IndexOf ('=');
+ n.SetAttribute (a.Substring (1, eq-1), a.Substring (eq+2, a.Length-eq-3));
+ }
+ e.AppendChild (n);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+class DocumentationMember {
+ public StringToStringMap MemberSignatures = new StringToStringMap ();
+ public string ReturnType;
+ public StringList Parameters;
+ public string MemberName;
+ public string MemberType;
+
+ public DocumentationMember (XmlReader reader)
+ {
+ MemberName = reader.GetAttribute ("MemberName");
+ int depth = reader.Depth;
+ bool go = true;
+ StringList p = new StringList ();
+ do {
+ if (reader.NodeType != XmlNodeType.Element)
+ continue;
+ switch (reader.Name) {
+ case "MemberSignature":
+ MemberSignatures [reader.GetAttribute ("Language")] = reader.GetAttribute ("Value");
+ break;
+ case "MemberType":
+ MemberType = reader.ReadElementString ();
+ break;
+ case "ReturnType":
+ if (reader.Depth == depth + 2)
ReturnType = reader.ReadElementString ();
break;
case "Parameter":
}
}
+public class DynamicParserContext {
+ public ReadOnlyCollection<bool> TransformFlags;
+ public int TransformIndex;
+
+ public DynamicParserContext (ICustomAttributeProvider provider)
+ {
+ CustomAttribute da;
+ if (provider.HasCustomAttributes &&
+ (da = (provider.CustomAttributes.Cast<CustomAttribute>()
+ .SingleOrDefault (ca => ca.GetDeclaringType() == "System.Runtime.CompilerServices.DynamicAttribute"))) != null) {
+ CustomAttributeArgument[] values = da.ConstructorArguments.Count == 0
+ ? new CustomAttributeArgument [0]
+ : (CustomAttributeArgument[]) da.ConstructorArguments [0].Value;
+
+ TransformFlags = new ReadOnlyCollection<bool> (values.Select (t => (bool) t.Value).ToArray());
+ }
+ }
+}
+
+public enum MemberFormatterState {
+ None,
+ WithinGenericTypeParameters,
+}
+
public abstract class MemberFormatter {
- public string GetName (MemberInfo member)
+
+ public virtual string Language {
+ get {return "";}
+ }
+
+ public string GetName (MemberReference member)
+ {
+ return GetName (member, null);
+ }
+
+ public virtual string GetName (MemberReference member, DynamicParserContext context)
{
- Type type = member as Type;
+ TypeReference type = member as TypeReference;
if (type != null)
- return GetTypeName (type);
- ConstructorInfo ctor = member as ConstructorInfo;
- if (ctor != null)
- return GetConstructorName (ctor);
- MethodInfo method = member as MethodInfo;
+ return GetTypeName (type, context);
+ MethodReference method = member as MethodReference;
+ if (method != null && method.Name == ".ctor") // method.IsConstructor
+ return GetConstructorName (method);
if (method != null)
return GetMethodName (method);
- PropertyInfo prop = member as PropertyInfo;
+ PropertyReference prop = member as PropertyReference;
if (prop != null)
return GetPropertyName (prop);
- FieldInfo field = member as FieldInfo;
+ FieldReference field = member as FieldReference;
if (field != null)
return GetFieldName (field);
- EventInfo e = member as EventInfo;
+ EventReference e = member as EventReference;
if (e != null)
return GetEventName (e);
- throw new NotSupportedException ("Can't handle: " + member.GetType().ToString());
+ throw new NotSupportedException ("Can't handle: " +
+ (member == null ? "null" : member.GetType().ToString()));
+ }
+
+ protected virtual string GetTypeName (TypeReference type)
+ {
+ return GetTypeName (type, null);
}
- protected virtual string GetTypeName (Type type)
+ protected virtual string GetTypeName (TypeReference type, DynamicParserContext context)
{
if (type == null)
throw new ArgumentNullException ("type");
- return _AppendTypeName (new StringBuilder (type.Name.Length), type).ToString ();
+ return _AppendTypeName (new StringBuilder (type.Name.Length), type, context).ToString ();
}
protected virtual char[] ArrayDelimeters {
get {return new char[]{'[', ']'};}
}
- protected StringBuilder _AppendTypeName (StringBuilder buf, Type type)
+ protected virtual MemberFormatterState MemberFormatterState { get; set; }
+
+ protected StringBuilder _AppendTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
{
- if (type.IsArray) {
- _AppendTypeName (buf, type.GetElementType ()).Append (ArrayDelimeters [0]);
- int rank = type.GetArrayRank ();
- if (rank > 1)
- buf.Append (new string (',', rank-1));
- return buf.Append (ArrayDelimeters [1]);
+ if (type is ArrayType) {
+ TypeSpecification spec = type as TypeSpecification;
+ _AppendTypeName (buf, spec != null ? spec.ElementType : type.GetElementType (), context);
+ return AppendArrayModifiers (buf, (ArrayType) type);
}
- if (type.IsByRef) {
- return AppendRefTypeName (buf, type);
+ if (type is ByReferenceType) {
+ return AppendRefTypeName (buf, type, context);
}
- if (type.IsPointer) {
- return AppendPointerTypeName (buf, type);
+ if (type is PointerType) {
+ return AppendPointerTypeName (buf, type, context);
}
AppendNamespace (buf, type);
- if (DocUtils.IsGenericParameter (type)) {
- return AppendTypeName (buf, type);
+ if (type is GenericParameter) {
+ return AppendTypeName (buf, type, context);
}
- if (!DocUtils.IsGenericType (type)) {
- return AppendFullTypeName (buf, type);
+ GenericInstanceType genInst = type as GenericInstanceType;
+ if (type.GenericParameters.Count == 0 &&
+ (genInst == null ? true : genInst.GenericArguments.Count == 0)) {
+ return AppendFullTypeName (buf, type, context);
}
- return AppendGenericType (buf, type);
+ return AppendGenericType (buf, type, context);
}
- protected virtual StringBuilder AppendNamespace (StringBuilder buf, Type type)
+ protected virtual StringBuilder AppendNamespace (StringBuilder buf, TypeReference type)
{
- if (type.Namespace != null && type.Namespace.Length > 0)
- buf.Append (type.Namespace).Append ('.');
+ string ns = DocUtils.GetNamespace (type);
+ if (ns != null && ns.Length > 0)
+ buf.Append (ns).Append ('.');
return buf;
}
- private StringBuilder AppendFullTypeName (StringBuilder buf, Type type)
+ protected virtual StringBuilder AppendFullTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
{
if (type.DeclaringType != null)
- AppendFullTypeName (buf, type.DeclaringType).Append (NestedTypeSeparator);
- return AppendTypeName (buf, type);
+ AppendFullTypeName (buf, type.DeclaringType, context).Append (NestedTypeSeparator);
+ return AppendTypeName (buf, type, context);
}
- protected virtual StringBuilder AppendTypeName (StringBuilder buf, Type type)
+ protected virtual StringBuilder AppendTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
{
+ if (context != null)
+ context.TransformIndex++;
return AppendTypeName (buf, type.Name);
}
return buf.Append (typename);
}
+ protected virtual StringBuilder AppendArrayModifiers (StringBuilder buf, ArrayType array)
+ {
+ buf.Append (ArrayDelimeters [0]);
+ int rank = array.Rank;
+ if (rank > 1)
+ buf.Append (new string (',', rank-1));
+ return buf.Append (ArrayDelimeters [1]);
+ }
+
protected virtual string RefTypeModifier {
get {return "@";}
}
- protected virtual StringBuilder AppendRefTypeName (StringBuilder buf, Type type)
+ protected virtual StringBuilder AppendRefTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
+ {
+ TypeSpecification spec = type as TypeSpecification;
+ return _AppendTypeName (buf, spec != null ? spec.ElementType : type.GetElementType (), context)
+ .Append (RefTypeModifier);
+ }
+
+ protected virtual string PointerModifier {
+ get {return "*";}
+ }
+
+ protected virtual StringBuilder AppendPointerTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
+ {
+ TypeSpecification spec = type as TypeSpecification;
+ return _AppendTypeName (buf, spec != null ? spec.ElementType : type.GetElementType (), context)
+ .Append (PointerModifier);
+ }
+
+ protected virtual char[] GenericTypeContainer {
+ get {return new char[]{'<', '>'};}
+ }
+
+ protected virtual char NestedTypeSeparator {
+ get {return '.';}
+ }
+
+ protected virtual StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, DynamicParserContext context)
+ {
+ List<TypeReference> decls = DocUtils.GetDeclaringTypes (
+ type is GenericInstanceType ? type.GetElementType () : type);
+ List<TypeReference> genArgs = GetGenericArguments (type);
+ int argIdx = 0;
+ int prev = 0;
+ bool insertNested = false;
+ foreach (var decl in decls) {
+ TypeReference declDef = decl.Resolve () ?? decl;
+ if (insertNested) {
+ buf.Append (NestedTypeSeparator);
+ }
+ insertNested = true;
+ AppendTypeName (buf, declDef, context);
+ int ac = DocUtils.GetGenericArgumentCount (declDef);
+ int c = ac - prev;
+ prev = ac;
+ if (c > 0) {
+ buf.Append (GenericTypeContainer [0]);
+ var origState = MemberFormatterState;
+ MemberFormatterState = MemberFormatterState.WithinGenericTypeParameters;
+ _AppendTypeName (buf, genArgs [argIdx++], context);
+ for (int i = 1; i < c; ++i) {
+ _AppendTypeName (buf.Append (","), genArgs [argIdx++], context);
+ }
+ MemberFormatterState = origState;
+ buf.Append (GenericTypeContainer [1]);
+ }
+ }
+ return buf;
+ }
+
+ protected List<TypeReference> GetGenericArguments (TypeReference type)
+ {
+ var args = new List<TypeReference> ();
+ GenericInstanceType inst = type as GenericInstanceType;
+ if (inst != null)
+ args.AddRange (inst.GenericArguments.Cast<TypeReference> ());
+ else
+ args.AddRange (type.GenericParameters.Cast<TypeReference> ());
+ return args;
+ }
+
+ protected virtual StringBuilder AppendGenericTypeConstraints (StringBuilder buf, TypeReference type)
+ {
+ return buf;
+ }
+
+ protected virtual string GetConstructorName (MethodReference constructor)
+ {
+ return constructor.Name;
+ }
+
+ protected virtual string GetMethodName (MethodReference method)
+ {
+ return method.Name;
+ }
+
+ protected virtual string GetPropertyName (PropertyReference property)
+ {
+ return property.Name;
+ }
+
+ protected virtual string GetFieldName (FieldReference field)
+ {
+ return field.Name;
+ }
+
+ protected virtual string GetEventName (EventReference e)
+ {
+ return e.Name;
+ }
+
+ public virtual string GetDeclaration (MemberReference member)
+ {
+ if (member == null)
+ throw new ArgumentNullException ("member");
+ TypeDefinition type = member as TypeDefinition;
+ if (type != null)
+ return GetTypeDeclaration (type);
+ MethodDefinition method = member as MethodDefinition;
+ if (method != null && method.IsConstructor)
+ return GetConstructorDeclaration (method);
+ if (method != null)
+ return GetMethodDeclaration (method);
+ PropertyDefinition prop = member as PropertyDefinition;
+ if (prop != null)
+ return GetPropertyDeclaration (prop);
+ FieldDefinition field = member as FieldDefinition;
+ if (field != null)
+ return GetFieldDeclaration (field);
+ EventDefinition e = member as EventDefinition;
+ if (e != null)
+ return GetEventDeclaration (e);
+ throw new NotSupportedException ("Can't handle: " + member.GetType().ToString());
+ }
+
+ protected virtual string GetTypeDeclaration (TypeDefinition type)
+ {
+ if (type == null)
+ throw new ArgumentNullException ("type");
+ StringBuilder buf = new StringBuilder (type.Name.Length);
+ _AppendTypeName (buf, type, null);
+ AppendGenericTypeConstraints (buf, type);
+ return buf.ToString ();
+ }
+
+ protected virtual string GetConstructorDeclaration (MethodDefinition constructor)
+ {
+ return GetConstructorName (constructor);
+ }
+
+ protected virtual string GetMethodDeclaration (MethodDefinition method)
+ {
+ if (method.HasCustomAttributes && method.CustomAttributes.Cast<CustomAttribute>().Any(
+ ca => ca.GetDeclaringType() == "System.Diagnostics.Contracts.ContractInvariantMethodAttribute"))
+ return null;
+
+ // Special signature for destructors.
+ if (method.Name == "Finalize" && method.Parameters.Count == 0)
+ return GetFinalizerName (method);
+
+ StringBuilder buf = new StringBuilder ();
+
+ AppendVisibility (buf, method);
+ if (buf.Length == 0 &&
+ !(DocUtils.IsExplicitlyImplemented (method) && !method.IsSpecialName))
+ return null;
+
+ AppendModifiers (buf, method);
+
+ if (buf.Length != 0)
+ buf.Append (" ");
+ buf.Append (GetTypeName (method.ReturnType, new DynamicParserContext (method.MethodReturnType))).Append (" ");
+
+ AppendMethodName (buf, method);
+ AppendGenericMethod (buf, method).Append (" ");
+ AppendParameters (buf, method, method.Parameters);
+ AppendGenericMethodConstraints (buf, method);
+ return buf.ToString ();
+ }
+
+ protected virtual StringBuilder AppendMethodName (StringBuilder buf, MethodDefinition method)
+ {
+ return buf.Append (method.Name);
+ }
+
+ protected virtual string GetFinalizerName (MethodDefinition method)
+ {
+ return "Finalize";
+ }
+
+ protected virtual StringBuilder AppendVisibility (StringBuilder buf, MethodDefinition method)
+ {
+ return buf;
+ }
+
+ protected virtual StringBuilder AppendModifiers (StringBuilder buf, MethodDefinition method)
+ {
+ return buf;
+ }
+
+ protected virtual StringBuilder AppendGenericMethod (StringBuilder buf, MethodDefinition method)
+ {
+ return buf;
+ }
+
+ protected virtual StringBuilder AppendParameters (StringBuilder buf, MethodDefinition method, IList<ParameterDefinition> parameters)
+ {
+ return buf;
+ }
+
+ protected virtual StringBuilder AppendGenericMethodConstraints (StringBuilder buf, MethodDefinition method)
+ {
+ return buf;
+ }
+
+ protected virtual string GetPropertyDeclaration (PropertyDefinition property)
+ {
+ return GetPropertyName (property);
+ }
+
+ protected virtual string GetFieldDeclaration (FieldDefinition field)
+ {
+ return GetFieldName (field);
+ }
+
+ protected virtual string GetEventDeclaration (EventDefinition e)
+ {
+ return GetEventName (e);
+ }
+}
+
+class ILFullMemberFormatter : MemberFormatter {
+
+ public override string Language {
+ get {return "ILAsm";}
+ }
+
+ protected override char NestedTypeSeparator {
+ get {
+ return '/';
+ }
+ }
+
+ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReference type)
+ {
+ if (GetBuiltinType (type.FullName) != null)
+ return buf;
+ string ns = DocUtils.GetNamespace (type);
+ if (ns != null && ns.Length > 0) {
+ if (type.IsValueType)
+ buf.Append ("valuetype ");
+ else
+ buf.Append ("class ");
+ buf.Append (ns).Append ('.');
+ }
+ return buf;
+ }
+
+ private static string GetBuiltinType (string t)
+ {
+ switch (t) {
+ case "System.Byte": return "unsigned int8";
+ case "System.SByte": return "int8";
+ case "System.Int16": return "int16";
+ case "System.Int32": return "int32";
+ case "System.Int64": return "int64";
+ case "System.IntPtr": return "native int";
+
+ case "System.UInt16": return "unsigned int16";
+ case "System.UInt32": return "unsigned int32";
+ case "System.UInt64": return "unsigned int64";
+ case "System.UIntPtr": return "native unsigned int";
+
+ case "System.Single": return "float32";
+ case "System.Double": return "float64";
+ 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 null;
+ }
+
+ protected override StringBuilder AppendTypeName (StringBuilder buf, string typename)
+ {
+ return buf.Append (typename);
+ }
+
+ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
+ {
+ if (type is GenericParameter) {
+ AppendGenericParameterConstraints (buf, (GenericParameter) type).Append (type.Name);
+ return buf;
+ }
+
+ string s = GetBuiltinType (type.FullName);
+ if (s != null) {
+ return buf.Append (s);
+ }
+ return base.AppendTypeName (buf, type, context);
+ }
+
+ private StringBuilder AppendGenericParameterConstraints (StringBuilder buf, GenericParameter type)
+ {
+ if (MemberFormatterState != MemberFormatterState.WithinGenericTypeParameters) {
+ return buf.Append (type.Owner is TypeReference ? "!" : "!!");
+ }
+ GenericParameterAttributes attrs = type.Attributes;
+ if ((attrs & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
+ buf.Append ("class ");
+ if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+ buf.Append ("struct ");
+ if ((attrs & GenericParameterAttributes.DefaultConstructorConstraint) != 0)
+ buf.Append (".ctor ");
+ IList<TypeReference> constraints = type.Constraints;
+ MemberFormatterState = 0;
+ if (constraints.Count > 0) {
+ var full = new ILFullMemberFormatter ();
+ buf.Append ("(").Append (full.GetName (constraints [0]));
+ for (int i = 1; i < constraints.Count; ++i) {
+ buf.Append (", ").Append (full.GetName (constraints [i]));
+ }
+ buf.Append (") ");
+ }
+ MemberFormatterState = MemberFormatterState.WithinGenericTypeParameters;
+
+ if ((attrs & GenericParameterAttributes.Covariant) != 0)
+ buf.Append ("+ ");
+ if ((attrs & GenericParameterAttributes.Contravariant) != 0)
+ buf.Append ("- ");
+ return buf;
+ }
+
+ protected override string GetTypeDeclaration (TypeDefinition type)
+ {
+ string visibility = GetTypeVisibility (type.Attributes);
+ if (visibility == null)
+ return null;
+
+ StringBuilder buf = new StringBuilder ();
+
+ buf.Append (".class ");
+ if (type.IsNested)
+ buf.Append ("nested ");
+ buf.Append (visibility).Append (" ");
+ if (type.IsInterface)
+ buf.Append ("interface ");
+ if (type.IsSequentialLayout)
+ buf.Append ("sequential ");
+ if (type.IsAutoLayout)
+ buf.Append ("auto ");
+ if (type.IsAnsiClass)
+ buf.Append ("ansi ");
+ if (type.IsAbstract)
+ buf.Append ("abstract ");
+ if (type.IsSerializable)
+ buf.Append ("serializable ");
+ if (type.IsSealed)
+ buf.Append ("sealed ");
+ if (type.IsBeforeFieldInit)
+ buf.Append ("beforefieldinit ");
+ var state = MemberFormatterState;
+ MemberFormatterState = MemberFormatterState.WithinGenericTypeParameters;
+ buf.Append (GetName (type));
+ MemberFormatterState = state;
+ var full = new ILFullMemberFormatter ();
+ if (type.BaseType != null) {
+ buf.Append (" extends ");
+ if (type.BaseType.FullName == "System.Object")
+ buf.Append ("System.Object");
+ else
+ buf.Append (full.GetName (type.BaseType).Substring ("class ".Length));
+ }
+ bool first = true;
+ foreach (var name in type.Interfaces
+ .Select (i => full.GetName (i))
+ .OrderBy (n => n)) {
+ if (first) {
+ buf.Append (" implements ");
+ first = false;
+ }
+ else {
+ buf.Append (", ");
+ }
+ buf.Append (name);
+ }
+
+ return buf.ToString ();
+ }
+
+ protected override StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, DynamicParserContext context)
+ {
+ List<TypeReference> decls = DocUtils.GetDeclaringTypes (
+ type is GenericInstanceType ? type.GetElementType () : type);
+ bool first = true;
+ foreach (var decl in decls) {
+ TypeReference declDef = decl.Resolve () ?? decl;
+ if (!first) {
+ buf.Append (NestedTypeSeparator);
+ }
+ first = false;
+ AppendTypeName (buf, declDef, context);
+ }
+ buf.Append ('<');
+ first = true;
+ foreach (TypeReference arg in GetGenericArguments (type)) {
+ if (!first)
+ buf.Append (", ");
+ first = false;
+ _AppendTypeName (buf, arg, context);
+ }
+ buf.Append ('>');
+ return buf;
+ }
+
+ static string GetTypeVisibility (TypeAttributes ta)
{
- return _AppendTypeName (buf, type.GetElementType ()).Append (RefTypeModifier);
- }
-
- protected virtual string PointerModifier {
- get {return "*";}
- }
+ switch (ta & TypeAttributes.VisibilityMask) {
+ case TypeAttributes.Public:
+ case TypeAttributes.NestedPublic:
+ return "public";
- protected virtual StringBuilder AppendPointerTypeName (StringBuilder buf, Type type)
- {
- return _AppendTypeName (buf, type.GetElementType ()).Append (PointerModifier);
- }
+ case TypeAttributes.NestedFamily:
+ case TypeAttributes.NestedFamORAssem:
+ return "protected";
- protected virtual char[] GenericTypeContainer {
- get {return new char[]{'<', '>'};}
+ default:
+ return null;
+ }
}
- protected virtual char NestedTypeSeparator {
- get {return '.';}
+ protected override string GetConstructorDeclaration (MethodDefinition constructor)
+ {
+ return GetMethodDeclaration (constructor);
}
- protected virtual StringBuilder AppendGenericType (StringBuilder buf, Type type)
+ protected override string GetMethodDeclaration (MethodDefinition method)
{
- Type[] genArgs = DocUtils.GetGenericArguments (type);
- int genArg = 0;
- if (type.DeclaringType != null) {
- AppendTypeName (buf, type.DeclaringType);
- if (DocUtils.IsGenericType (type.DeclaringType)) {
- buf.Append (GenericTypeContainer [0]);
- int max = DocUtils.GetGenericArguments (type.DeclaringType).Length;
- _AppendTypeName (buf, genArgs [genArg++]);
- while (genArg < max) {
- buf.Append (",");
- _AppendTypeName (buf, genArgs [genArg++]);
- }
- buf.Append (GenericTypeContainer [1]);
- }
- buf.Append (NestedTypeSeparator);
- }
- AppendTypeName (buf, type);
- if (genArg < genArgs.Length) {
- buf.Append (GenericTypeContainer [0]);
- _AppendTypeName (buf, genArgs [genArg++]);
- while (genArg < genArgs.Length) {
- buf.Append (",");
- _AppendTypeName (buf, genArgs [genArg++]);
+ if (method.IsPrivate && !DocUtils.IsExplicitlyImplemented (method))
+ return null;
+
+ var buf = new StringBuilder ();
+ buf.Append (".method ");
+ AppendVisibility (buf, method);
+ if (method.IsStatic)
+ buf.Append ("static ");
+ if (method.IsHideBySig)
+ buf.Append ("hidebysig ");
+ if (method.IsPInvokeImpl) {
+ var info = method.PInvokeInfo;
+ buf.Append ("pinvokeimpl (\"")
+ .Append (info.Module.Name)
+ .Append ("\" as \"")
+ .Append (info.EntryPoint)
+ .Append ("\"");
+ if (info.IsCharSetAuto)
+ buf.Append (" auto");
+ if (info.IsCharSetUnicode)
+ buf.Append (" unicode");
+ if (info.IsCharSetAnsi)
+ buf.Append (" ansi");
+ if (info.IsCallConvCdecl)
+ buf.Append (" cdecl");
+ if (info.IsCallConvStdCall)
+ buf.Append (" stdcall");
+ if (info.IsCallConvWinapi)
+ buf.Append (" winapi");
+ if (info.IsCallConvThiscall)
+ buf.Append (" thiscall");
+ if (info.SupportsLastError)
+ buf.Append (" lasterr");
+ buf.Append (")");
+ }
+ if (method.IsSpecialName)
+ buf.Append ("specialname ");
+ if (method.IsRuntimeSpecialName)
+ buf.Append ("rtspecialname ");
+ if (method.IsNewSlot)
+ buf.Append ("newslot ");
+ if (method.IsVirtual)
+ buf.Append ("virtual ");
+ if (!method.IsStatic)
+ buf.Append ("instance ");
+ _AppendTypeName (buf, method.ReturnType, new DynamicParserContext (method.MethodReturnType));
+ buf.Append (' ')
+ .Append (method.Name);
+ if (method.IsGenericMethod ()) {
+ var state = MemberFormatterState;
+ MemberFormatterState = MemberFormatterState.WithinGenericTypeParameters;
+ IList<GenericParameter> args = method.GenericParameters;
+ if (args.Count > 0) {
+ buf.Append ("<");
+ _AppendTypeName (buf, args [0], null);
+ for (int i = 1; i < args.Count; ++i)
+ _AppendTypeName (buf.Append (", "), args [i], null);
+ buf.Append (">");
}
- buf.Append (GenericTypeContainer [1]);
+ MemberFormatterState = state;
}
- return buf;
- }
- protected virtual StringBuilder AppendGenericTypeConstraints (StringBuilder buf, Type type)
- {
- return buf;
+ buf.Append ('(');
+ bool first = true;
+ for (int i = 0; i < method.Parameters.Count; ++i) {
+ if (!first)
+ buf.Append (", ");
+ first = false;
+ _AppendTypeName (buf, method.Parameters [i].ParameterType, new DynamicParserContext (method.Parameters [i]));
+ buf.Append (' ');
+ buf.Append (method.Parameters [i].Name);
+ }
+ buf.Append (')');
+ if (method.IsIL)
+ buf.Append (" cil");
+ if (method.IsRuntime)
+ buf.Append (" runtime");
+ if (method.IsManaged)
+ buf.Append (" managed");
+
+ return buf.ToString ();
}
- protected virtual string GetConstructorName (ConstructorInfo constructor)
+ protected override StringBuilder AppendMethodName (StringBuilder buf, MethodDefinition method)
{
- return constructor.Name;
+ if (DocUtils.IsExplicitlyImplemented (method)) {
+ TypeReference iface;
+ MethodReference ifaceMethod;
+ DocUtils.GetInfoForExplicitlyImplementedMethod (method, out iface, out ifaceMethod);
+ return buf.Append (new CSharpMemberFormatter ().GetName (iface))
+ .Append ('.')
+ .Append (ifaceMethod.Name);
+ }
+ return base.AppendMethodName (buf, method);
}
- protected virtual string GetMethodName (MethodInfo method)
- {
- return method.Name;
+ protected override string RefTypeModifier {
+ get {return "";}
}
- protected virtual string GetPropertyName (PropertyInfo property)
+ protected override StringBuilder AppendVisibility (StringBuilder buf, MethodDefinition method)
{
- return property.Name;
+ if (method.IsPublic)
+ return buf.Append ("public ");
+ if (method.IsFamilyAndAssembly)
+ return buf.Append ("familyandassembly");
+ if (method.IsFamilyOrAssembly)
+ return buf.Append ("familyorassembly");
+ if (method.IsFamily)
+ return buf.Append ("family");
+ return buf;
}
- protected virtual string GetFieldName (FieldInfo field)
+ protected override StringBuilder AppendModifiers (StringBuilder buf, MethodDefinition method)
{
- return field.Name;
+ string modifiers = String.Empty;
+ if (method.IsStatic) modifiers += " static";
+ if (method.IsVirtual && !method.IsAbstract) {
+ if ((method.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual";
+ else modifiers += " override";
+ }
+ TypeDefinition declType = (TypeDefinition) method.DeclaringType;
+ if (method.IsAbstract && !declType.IsInterface) modifiers += " abstract";
+ if (method.IsFinal) modifiers += " sealed";
+ if (modifiers == " virtual sealed") modifiers = "";
+
+ return buf.Append (modifiers);
}
- protected virtual string GetEventName (EventInfo e)
+ protected override StringBuilder AppendGenericMethod (StringBuilder buf, MethodDefinition method)
{
- return e.Name;
+ if (method.IsGenericMethod ()) {
+ IList<GenericParameter> args = method.GenericParameters;
+ if (args.Count > 0) {
+ buf.Append ("<");
+ buf.Append (args [0].Name);
+ for (int i = 1; i < args.Count; ++i)
+ buf.Append (",").Append (args [i].Name);
+ buf.Append (">");
+ }
+ }
+ return buf;
}
- public string GetDeclaration (MemberInfo member)
+ protected override StringBuilder AppendParameters (StringBuilder buf, MethodDefinition method, IList<ParameterDefinition> parameters)
{
- Type type = member as Type;
- if (type != null)
- return GetTypeDeclaration (type);
- ConstructorInfo ctor = member as ConstructorInfo;
- if (ctor != null)
- return GetConstructorDeclaration (ctor);
- MethodInfo method = member as MethodInfo;
- if (method != null)
- return GetMethodDeclaration (method);
- PropertyInfo prop = member as PropertyInfo;
- if (prop != null)
- return GetPropertyDeclaration (prop);
- FieldInfo field = member as FieldInfo;
- if (field != null)
- return GetFieldDeclaration (field);
- EventInfo e = member as EventInfo;
- if (e != null)
- return GetEventDeclaration (e);
- throw new NotSupportedException ("Can't handle: " + member.GetType().ToString());
+ return AppendParameters (buf, method, parameters, '(', ')');
}
- protected virtual string GetTypeDeclaration (Type type)
+ private StringBuilder AppendParameters (StringBuilder buf, MethodDefinition method, IList<ParameterDefinition> parameters, char begin, char end)
{
- if (type == null)
- throw new ArgumentNullException ("type");
- StringBuilder buf = new StringBuilder (type.Name.Length);
- _AppendTypeName (buf, type);
- AppendGenericTypeConstraints (buf, type);
- return buf.ToString ();
+ buf.Append (begin);
+
+ if (parameters.Count > 0) {
+ if (DocUtils.IsExtensionMethod (method))
+ buf.Append ("this ");
+ AppendParameter (buf, parameters [0]);
+ for (int i = 1; i < parameters.Count; ++i) {
+ buf.Append (", ");
+ AppendParameter (buf, parameters [i]);
+ }
+ }
+
+ return buf.Append (end);
}
- protected virtual string GetConstructorDeclaration (ConstructorInfo constructor)
+ private StringBuilder AppendParameter (StringBuilder buf, ParameterDefinition parameter)
{
- return GetConstructorName (constructor);
+ if (parameter.ParameterType is ByReferenceType) {
+ if (parameter.IsOut)
+ buf.Append ("out ");
+ else
+ buf.Append ("ref ");
+ }
+ buf.Append (GetName (parameter.ParameterType)).Append (" ");
+ return buf.Append (parameter.Name);
}
- protected virtual string GetMethodDeclaration (MethodInfo method)
+ protected override string GetPropertyDeclaration (PropertyDefinition property)
{
- // Special signature for destructors.
- if (method.Name == "Finalize" && method.GetParameters().Length == 0)
- return GetFinalizerName (method);
+ MethodDefinition gm = null, sm = null;
- StringBuilder buf = new StringBuilder ();
+ string get_visible = null;
+ if ((gm = property.GetMethod) != null &&
+ (DocUtils.IsExplicitlyImplemented (gm) ||
+ (!gm.IsPrivate && !gm.IsAssembly && !gm.IsFamilyAndAssembly)))
+ get_visible = AppendVisibility (new StringBuilder (), gm).ToString ();
+ string set_visible = null;
+ if ((sm = property.SetMethod) != null &&
+ (DocUtils.IsExplicitlyImplemented (sm) ||
+ (!sm.IsPrivate && !sm.IsAssembly && !sm.IsFamilyAndAssembly)))
+ set_visible = AppendVisibility (new StringBuilder (), sm).ToString ();
- AppendVisibility (buf, method);
- if (buf.Length == 0 &&
- !(DocUtils.IsExplicitlyImplemented (method) && !method.IsSpecialName))
+ if ((set_visible == null) && (get_visible == null))
return null;
- AppendModifiers (buf, method);
+ StringBuilder buf = new StringBuilder ()
+ .Append (".property ");
+ if (!(gm ?? sm).IsStatic)
+ buf.Append ("instance ");
+ _AppendTypeName (buf, property.PropertyType, new DynamicParserContext (property));
+ buf.Append (' ').Append (property.Name);
+ if (!property.HasParameters || property.Parameters.Count == 0)
+ return buf.ToString ();
- if (buf.Length != 0)
- buf.Append (" ");
- buf.Append (GetName (method.ReturnType)).Append (" ");
+ buf.Append ('(');
+ bool first = true;
+ foreach (ParameterDefinition p in property.Parameters) {
+ if (!first)
+ buf.Append (", ");
+ first = false;
+ _AppendTypeName (buf, p.ParameterType, new DynamicParserContext (p));
+ }
+ buf.Append (')');
- AppendMethodName (buf, method);
- AppendGenericMethod (buf, method).Append (" ");
- AppendParameters (buf, method, method.GetParameters ());
- AppendGenericMethodConstraints (buf, method);
return buf.ToString ();
}
- protected virtual StringBuilder AppendMethodName (StringBuilder buf, MethodBase method)
+ protected override string GetFieldDeclaration (FieldDefinition field)
{
- return buf.Append (method.Name);
- }
+ TypeDefinition declType = (TypeDefinition) field.DeclaringType;
+ if (declType.IsEnum && field.Name == "value__")
+ return null; // This member of enums aren't documented.
- protected virtual string GetFinalizerName (MethodInfo method)
- {
- return "Finalize";
- }
+ StringBuilder buf = new StringBuilder ();
+ AppendFieldVisibility (buf, field);
+ if (buf.Length == 0)
+ return null;
- protected virtual StringBuilder AppendVisibility (StringBuilder buf, MethodBase method)
- {
- return buf;
- }
+ buf.Insert (0, ".field ");
- protected virtual StringBuilder AppendModifiers (StringBuilder buf, MethodInfo method)
- {
- return buf;
- }
+ if (field.IsStatic)
+ buf.Append ("static ");
+ if (field.IsInitOnly)
+ buf.Append ("initonly ");
+ if (field.IsLiteral)
+ buf.Append ("literal ");
+ _AppendTypeName (buf, field.FieldType, new DynamicParserContext (field));
+ buf.Append (' ').Append (field.Name);
+ AppendFieldValue (buf, field);
- protected virtual StringBuilder AppendGenericMethod (StringBuilder buf, MethodInfo method)
- {
- return buf;
+ return buf.ToString ();
}
- protected virtual StringBuilder AppendParameters (StringBuilder buf, MethodBase method, ParameterInfo[] parameters)
+ static StringBuilder AppendFieldVisibility (StringBuilder buf, FieldDefinition field)
{
+ if (field.IsPublic)
+ return buf.Append ("public ");
+ if (field.IsFamilyAndAssembly)
+ return buf.Append ("familyandassembly ");
+ if (field.IsFamilyOrAssembly)
+ return buf.Append ("familyorassembly ");
+ if (field.IsFamily)
+ return buf.Append ("family ");
return buf;
}
- protected virtual StringBuilder AppendGenericMethodConstraints (StringBuilder buf, MethodInfo method)
+ static StringBuilder AppendFieldValue (StringBuilder buf, FieldDefinition field)
{
+ // enums have a value__ field, which we ignore
+ if (field.DeclaringType.IsGenericType ())
+ return buf;
+ if (field.HasConstant && field.IsLiteral) {
+ object val = null;
+ try {
+ val = field.Constant;
+ } catch {
+ return buf;
+ }
+ if (val == null)
+ buf.Append (" = ").Append ("null");
+ else if (val is Enum)
+ buf.Append (" = ")
+ .Append (GetBuiltinType (field.DeclaringType.GetUnderlyingType ().FullName))
+ .Append ('(')
+ .Append (val.ToString ())
+ .Append (')');
+ else if (val is IFormattable) {
+ string value = ((IFormattable)val).ToString();
+ buf.Append (" = ");
+ if (val is string)
+ buf.Append ("\"" + value + "\"");
+ else
+ buf.Append (GetBuiltinType (field.DeclaringType.GetUnderlyingType ().FullName))
+ .Append ('(')
+ .Append (value)
+ .Append (')');
+ }
+ }
return buf;
}
- protected virtual string GetPropertyDeclaration (PropertyInfo property)
+ protected override string GetEventDeclaration (EventDefinition e)
{
- return GetPropertyName (property);
- }
+ StringBuilder buf = new StringBuilder ();
+ if (AppendVisibility (buf, e.AddMethod).Length == 0) {
+ return null;
+ }
- protected virtual string GetFieldDeclaration (FieldInfo field)
- {
- return GetFieldName (field);
+ buf.Length = 0;
+ buf.Append (".event ")
+ .Append (GetName (e.EventType))
+ .Append (' ')
+ .Append (e.Name);
+
+ return buf.ToString ();
}
+}
- protected virtual string GetEventDeclaration (EventInfo e)
+class ILMemberFormatter : ILFullMemberFormatter {
+ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReference type)
{
- return GetEventName (e);
+ return buf;
}
}
class CSharpFullMemberFormatter : MemberFormatter {
- protected override StringBuilder AppendNamespace (StringBuilder buf, Type type)
+ public override string Language {
+ get {return "C#";}
+ }
+
+ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReference type)
{
- if (GetCSharpType (type.FullName) == null && type.Namespace != null && type.Namespace.Length > 0 && type.Namespace != "System")
- buf.Append (type.Namespace).Append ('.');
+ string ns = DocUtils.GetNamespace (type);
+ if (GetCSharpType (type.FullName) == null && ns != null && ns.Length > 0 && ns != "System")
+ buf.Append (ns).Append ('.');
return buf;
}
return null;
}
- protected override StringBuilder AppendTypeName (StringBuilder buf, Type type)
+ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
{
- if (DocUtils.IsGenericParameter (type))
- return buf.Append (type.Name);
+ if (context != null && context.TransformFlags != null &&
+ (context.TransformFlags.Count == 0 || context.TransformFlags [context.TransformIndex])) {
+ context.TransformIndex++;
+ return buf.Append ("dynamic");
+ }
+
+ if (type is GenericParameter)
+ return AppendGenericParameterConstraints (buf, (GenericParameter) type, context).Append (type.Name);
string t = type.FullName;
if (!t.StartsWith ("System.")) {
- return base.AppendTypeName (buf, type);
+ return base.AppendTypeName (buf, type, context);
}
string s = GetCSharpType (t);
- if (s != null)
+ if (s != null) {
+ if (context != null)
+ context.TransformIndex++;
return buf.Append (s);
+ }
- return base.AppendTypeName (buf, type);
+ return base.AppendTypeName (buf, type, context);
}
- protected override string GetTypeDeclaration (Type type)
+ private StringBuilder AppendGenericParameterConstraints (StringBuilder buf, GenericParameter type, DynamicParserContext context)
+ {
+ if (MemberFormatterState != MemberFormatterState.WithinGenericTypeParameters)
+ return buf;
+ GenericParameterAttributes attrs = type.Attributes;
+ bool isout = (attrs & GenericParameterAttributes.Covariant) != 0;
+ bool isin = (attrs & GenericParameterAttributes.Contravariant) != 0;
+ if (isin)
+ buf.Append ("in ");
+ else if (isout)
+ buf.Append ("out ");
+ return buf;
+ }
+
+ protected override string GetTypeDeclaration (TypeDefinition type)
{
string visibility = GetTypeVisibility (type.Attributes);
if (visibility == null)
MemberFormatter full = new CSharpFullMemberFormatter ();
- if (IsDelegate(type)) {
+ if (DocUtils.IsDelegate (type)) {
buf.Append("delegate ");
- MethodInfo invoke = type.GetMethod ("Invoke");
- buf.Append (full.GetName (invoke.ReturnType)).Append (" ");
+ MethodDefinition invoke = type.GetMethod ("Invoke");
+ buf.Append (full.GetName (invoke.ReturnType, new DynamicParserContext (invoke.MethodReturnType))).Append (" ");
buf.Append (GetName (type));
- AppendParameters (buf, invoke, invoke.GetParameters ());
+ AppendParameters (buf, invoke, invoke.Parameters);
AppendGenericTypeConstraints (buf, type);
buf.Append (";");
if (type.IsAbstract && !type.IsInterface)
buf.Append("abstract ");
- if (type.IsSealed && !IsDelegate(type) && !type.IsValueType)
+ if (type.IsSealed && !DocUtils.IsDelegate (type) && !type.IsValueType)
buf.Append("sealed ");
buf.Replace ("abstract sealed", "static");
: type.Name);
if (!type.IsEnum) {
- Type basetype = type.BaseType;
- if (basetype == typeof(object) || type.IsValueType) // don't show this in signatures
+ TypeReference basetype = type.BaseType;
+ if (basetype != null && basetype.FullName == "System.Object" || type.IsValueType) // FIXME
basetype = null;
-
- ArrayList interface_names = new ArrayList ();
- foreach (Type i in type.GetInterfaces ())
- if ((type.BaseType == null || Array.IndexOf (type.BaseType.GetInterfaces (), i) == -1) &&
- InterfaceNotFromAnother (i, type.GetInterfaces ()))
- interface_names.Add (full.GetName (i));
- interface_names.Sort ();
-
+
+ List<string> interface_names = DocUtils.GetUserImplementedInterfaces (type)
+ .Select (iface => full.GetName (iface))
+ .OrderBy (s => s)
+ .ToList ();
+
if (basetype != null || interface_names.Count > 0)
buf.Append (" : ");
return buf.ToString ();
}
- static string GetTypeKind (Type t)
+ static string GetTypeKind (TypeDefinition t)
{
if (t.IsEnum)
return "enum";
- if (t.IsClass || t == typeof(System.Enum))
+ if (t.IsValueType)
+ return "struct";
+ if (t.IsClass || t.FullName == "System.Enum")
return "class";
if (t.IsInterface)
return "interface";
- if (t.IsValueType)
- return "struct";
throw new ArgumentException(t.FullName);
}
}
}
- static bool IsDelegate(Type type)
- {
- return typeof (System.Delegate).IsAssignableFrom (type) && !type.IsAbstract;
- }
-
- private static bool InterfaceNotFromAnother(Type i, Type[] i2)
- {
- foreach (Type t in i2)
- if (i != t && Array.IndexOf (t.GetInterfaces(), i) != -1)
- return false;
- return true;
- }
-
- protected override StringBuilder AppendGenericTypeConstraints (StringBuilder buf, Type type)
+ protected override StringBuilder AppendGenericTypeConstraints (StringBuilder buf, TypeReference type)
{
- if (!DocUtils.GetContainsGenericParameters (type))
+ if (type.GenericParameters.Count == 0)
return buf;
- return AppendConstraints (buf, DocUtils.GetGenericArguments (type));
+ return AppendConstraints (buf, type.GenericParameters);
}
- private StringBuilder AppendConstraints (StringBuilder buf, Type[] genArgs)
+ private StringBuilder AppendConstraints (StringBuilder buf, IList<GenericParameter> genArgs)
{
-#if !NET_1_0
- foreach (Type genArg in genArgs) {
- GenericParameterAttributes attrs = genArg.GenericParameterAttributes;
- Type[] constraints = genArg.GetGenericParameterConstraints ();
- if (attrs == GenericParameterAttributes.None && constraints.Length == 0)
+ foreach (GenericParameter genArg in genArgs) {
+ GenericParameterAttributes attrs = genArg.Attributes;
+ IList<TypeReference> constraints = genArg.Constraints;
+ if (attrs == GenericParameterAttributes.NonVariant && constraints.Count == 0)
continue;
- buf.Append (" where ").Append (genArg.Name).Append (" : ");
+
bool isref = (attrs & GenericParameterAttributes.ReferenceTypeConstraint) != 0;
bool isvt = (attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0;
bool isnew = (attrs & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
bool comma = false;
+
+ if (!isref && !isvt && !isnew && constraints.Count == 0)
+ continue;
+ buf.Append (" where ").Append (genArg.Name).Append (" : ");
if (isref) {
buf.Append ("class");
comma = true;
buf.Append ("struct");
comma = true;
}
- if (constraints.Length > 0 && !isvt) {
+ if (constraints.Count > 0 && !isvt) {
if (comma)
buf.Append (", ");
buf.Append (GetTypeName (constraints [0]));
- for (int i = 1; i < constraints.Length; ++i)
+ for (int i = 1; i < constraints.Count; ++i)
buf.Append (", ").Append (GetTypeName (constraints [i]));
}
if (isnew && !isvt) {
buf.Append ("new()");
}
}
-#endif
return buf;
}
- protected override string GetConstructorDeclaration (ConstructorInfo constructor)
+ protected override string GetConstructorDeclaration (MethodDefinition constructor)
{
StringBuilder buf = new StringBuilder ();
AppendVisibility (buf, constructor);
buf.Append (' ');
base.AppendTypeName (buf, constructor.DeclaringType.Name).Append (' ');
- AppendParameters (buf, constructor, constructor.GetParameters ());
+ AppendParameters (buf, constructor, constructor.Parameters);
buf.Append (';');
return buf.ToString ();
}
- protected override string GetMethodDeclaration (MethodInfo method)
+ protected override string GetMethodDeclaration (MethodDefinition method)
{
string decl = base.GetMethodDeclaration (method);
if (decl != null)
return null;
}
- protected override StringBuilder AppendMethodName (StringBuilder buf, MethodBase method)
+ protected override StringBuilder AppendMethodName (StringBuilder buf, MethodDefinition method)
{
if (DocUtils.IsExplicitlyImplemented (method)) {
- Type iface;
- MethodInfo ifaceMethod;
+ TypeReference iface;
+ MethodReference ifaceMethod;
DocUtils.GetInfoForExplicitlyImplementedMethod (method, out iface, out ifaceMethod);
return buf.Append (new CSharpMemberFormatter ().GetName (iface))
.Append ('.')
return base.AppendMethodName (buf, method);
}
- protected override StringBuilder AppendGenericMethodConstraints (StringBuilder buf, MethodInfo method)
+ protected override StringBuilder AppendGenericMethodConstraints (StringBuilder buf, MethodDefinition method)
{
- if (!DocUtils.GetContainsGenericParameters (method))
+ if (method.GenericParameters.Count == 0)
return buf;
- return AppendConstraints (buf, DocUtils.GetGenericArguments (method));
+ return AppendConstraints (buf, method.GenericParameters);
}
protected override string RefTypeModifier {
get {return "";}
}
- protected override string GetFinalizerName (MethodInfo method)
+ protected override string GetFinalizerName (MethodDefinition method)
{
return "~" + method.DeclaringType.Name + " ()";
}
- protected override StringBuilder AppendVisibility (StringBuilder buf, MethodBase method)
+ protected override StringBuilder AppendVisibility (StringBuilder buf, MethodDefinition method)
{
if (method == null)
return buf;
return buf;
}
- protected override StringBuilder AppendModifiers (StringBuilder buf, MethodInfo method)
+ protected override StringBuilder AppendModifiers (StringBuilder buf, MethodDefinition method)
{
string modifiers = String.Empty;
if (method.IsStatic) modifiers += " static";
if ((method.Attributes & MethodAttributes.NewSlot) != 0) modifiers += " virtual";
else modifiers += " override";
}
- if (method.IsAbstract && !method.DeclaringType.IsInterface) modifiers += " abstract";
+ TypeDefinition declType = (TypeDefinition) method.DeclaringType;
+ if (method.IsAbstract && !declType.IsInterface) modifiers += " abstract";
if (method.IsFinal) modifiers += " sealed";
if (modifiers == " virtual sealed") modifiers = "";
return buf.Append (modifiers);
}
- protected override StringBuilder AppendGenericMethod (StringBuilder buf, MethodInfo method)
+ protected override StringBuilder AppendGenericMethod (StringBuilder buf, MethodDefinition method)
{
- if (DocUtils.GetContainsGenericParameters (method)) {
- Type[] args = DocUtils.GetGenericArguments (method);
- if (args.Length > 0) {
+ if (method.IsGenericMethod ()) {
+ IList<GenericParameter> args = method.GenericParameters;
+ if (args.Count > 0) {
buf.Append ("<");
buf.Append (args [0].Name);
- for (int i = 1; i < args.Length; ++i)
+ for (int i = 1; i < args.Count; ++i)
buf.Append (",").Append (args [i].Name);
buf.Append (">");
}
return buf;
}
- protected override StringBuilder AppendParameters (StringBuilder buf, MethodBase method, ParameterInfo[] parameters)
+ protected override StringBuilder AppendParameters (StringBuilder buf, MethodDefinition method, IList<ParameterDefinition> parameters)
{
return AppendParameters (buf, method, parameters, '(', ')');
}
- private StringBuilder AppendParameters (StringBuilder buf, MethodBase method, ParameterInfo[] parameters, char begin, char end)
+ private StringBuilder AppendParameters (StringBuilder buf, MethodDefinition method, IList<ParameterDefinition> parameters, char begin, char end)
{
buf.Append (begin);
- if (parameters.Length > 0) {
+ if (parameters.Count > 0) {
if (DocUtils.IsExtensionMethod (method))
buf.Append ("this ");
AppendParameter (buf, parameters [0]);
- for (int i = 1; i < parameters.Length; ++i) {
+ for (int i = 1; i < parameters.Count; ++i) {
buf.Append (", ");
AppendParameter (buf, parameters [i]);
}
return buf.Append (end);
}
- private StringBuilder AppendParameter (StringBuilder buf, ParameterInfo parameter)
+ private StringBuilder AppendParameter (StringBuilder buf, ParameterDefinition parameter)
{
- if (parameter.ParameterType.IsByRef) {
+ if (parameter.ParameterType is ByReferenceType) {
if (parameter.IsOut)
buf.Append ("out ");
else
buf.Append ("ref ");
}
- buf.Append (GetName (parameter.ParameterType)).Append (" ");
- return buf.Append (parameter.Name);
+ buf.Append (GetTypeName (parameter.ParameterType, new DynamicParserContext (parameter))).Append (" ");
+ buf.Append (parameter.Name);
+ if (parameter.HasDefault && parameter.IsOptional && parameter.HasConstant) {
+ buf.AppendFormat (" = {0}", MDocUpdater.MakeAttributesValueString (parameter.Constant, parameter.ParameterType));
+ }
+ return buf;
}
- protected override string GetPropertyDeclaration (PropertyInfo property)
+ protected override string GetPropertyDeclaration (PropertyDefinition property)
{
- MethodInfo method;
+ MethodDefinition method;
string get_visible = null;
- if ((method = property.GetGetMethod (true)) != null &&
+ if ((method = property.GetMethod) != null &&
(DocUtils.IsExplicitlyImplemented (method) ||
(!method.IsPrivate && !method.IsAssembly && !method.IsFamilyAndAssembly)))
get_visible = AppendVisibility (new StringBuilder (), method).ToString ();
string set_visible = null;
- if ((method = property.GetSetMethod (true)) != null &&
+ if ((method = property.SetMethod) != null &&
(DocUtils.IsExplicitlyImplemented (method) ||
(!method.IsPrivate && !method.IsAssembly && !method.IsFamilyAndAssembly)))
set_visible = AppendVisibility (new StringBuilder (), method).ToString ();
buf.Append (visibility = "public");
// Pick an accessor to use for static/virtual/override/etc. checks.
- method = property.GetSetMethod (true);
+ method = property.SetMethod;
if (method == null)
- method = property.GetGetMethod (true);
+ method = property.GetMethod;
string modifiers = String.Empty;
if (method.IsStatic) modifiers += " static";
else
modifiers += " override";
}
- if (method.IsAbstract && !method.DeclaringType.IsInterface)
+ TypeDefinition declDef = (TypeDefinition) method.DeclaringType;
+ if (method.IsAbstract && !declDef.IsInterface)
modifiers += " abstract";
if (method.IsFinal)
modifiers += " sealed";
modifiers = "";
buf.Append (modifiers).Append (' ');
- buf.Append (GetName (property.PropertyType)).Append (' ');
-
- MemberInfo[] defs = property.DeclaringType.GetDefaultMembers ();
+ buf.Append (GetTypeName (property.PropertyType, new DynamicParserContext (property))).Append (' ');
+
+ IEnumerable<MemberReference> defs = property.DeclaringType.GetDefaultMembers ();
string name = property.Name;
- foreach (MemberInfo mi in defs) {
+ foreach (MemberReference mi in defs) {
if (mi == property) {
name = "this";
break;
}
buf.Append (name == "this" ? name : DocUtils.GetPropertyName (property));
- if (property.GetIndexParameters ().Length != 0) {
- AppendParameters (buf, method, property.GetIndexParameters (), '[', ']');
+ if (property.Parameters.Count != 0) {
+ AppendParameters (buf, method, property.Parameters, '[', ']');
}
buf.Append (" {");
- if (set_visible != null) {
- if (set_visible != visibility)
- buf.Append (' ').Append (set_visible);
- buf.Append (" set;");
- }
if (get_visible != null) {
if (get_visible != visibility)
buf.Append (' ').Append (get_visible);
buf.Append (" get;");
}
+ if (set_visible != null) {
+ if (set_visible != visibility)
+ buf.Append (' ').Append (set_visible);
+ buf.Append (" set;");
+ }
buf.Append (" }");
return buf [0] != ' ' ? buf.ToString () : buf.ToString (1, buf.Length-1);
}
- protected override string GetFieldDeclaration (FieldInfo field)
+ protected override string GetFieldDeclaration (FieldDefinition field)
{
- if (field.DeclaringType.IsEnum && field.Name == "value__")
+ TypeDefinition declType = (TypeDefinition) field.DeclaringType;
+ if (declType.IsEnum && field.Name == "value__")
return null; // This member of enums aren't documented.
StringBuilder buf = new StringBuilder ();
if (buf.Length == 0)
return null;
- if (field.DeclaringType.IsEnum)
+ if (declType.IsEnum)
return field.Name;
if (field.IsStatic && !field.IsLiteral)
if (field.IsLiteral)
buf.Append (" const");
- buf.Append (' ').Append (GetName (field.FieldType)).Append (' ');
+ buf.Append (' ').Append (GetTypeName (field.FieldType, new DynamicParserContext (field))).Append (' ');
buf.Append (field.Name);
AppendFieldValue (buf, field);
buf.Append (';');
return buf.ToString ();
}
- static StringBuilder AppendFieldVisibility (StringBuilder buf, FieldInfo field)
+ static StringBuilder AppendFieldVisibility (StringBuilder buf, FieldDefinition field)
{
if (field.IsPublic)
return buf.Append ("public");
return buf;
}
- static StringBuilder AppendFieldValue (StringBuilder buf, FieldInfo field)
+ static StringBuilder AppendFieldValue (StringBuilder buf, FieldDefinition field)
{
- // enums have a value__ field, which we ignore, and FieldInfo.GetValue()
- // on a GenericType results in InvalidOperationException
- if (field.DeclaringType.IsEnum ||
- DocUtils.IsGenericType (field.DeclaringType))
+ // enums have a value__ field, which we ignore
+ if (((TypeDefinition ) field.DeclaringType).IsEnum ||
+ field.DeclaringType.IsGenericType ())
return buf;
- if (field.IsLiteral || (field.IsStatic && field.IsInitOnly)) {
+ if (field.HasConstant && field.IsLiteral) {
object val = null;
try {
- val = field.GetValue (null);
+ val = field.Constant;
} catch {
return buf;
}
return buf;
}
- protected override string GetEventDeclaration (EventInfo e)
+ protected override string GetEventDeclaration (EventDefinition e)
{
StringBuilder buf = new StringBuilder ();
- if (AppendVisibility (buf, e.GetAddMethod (true)).Length == 0) {
+ if (AppendVisibility (buf, e.AddMethod).Length == 0) {
return null;
}
- AppendModifiers (buf, e.GetAddMethod (true));
+ AppendModifiers (buf, e.AddMethod);
buf.Append (" event ");
- buf.Append (GetName (e.EventHandlerType)).Append (' ');
+ buf.Append (GetTypeName (e.EventType, new DynamicParserContext (e.AddMethod.Parameters [0]))).Append (' ');
buf.Append (e.Name).Append (';');
return buf.ToString ();
}
class CSharpMemberFormatter : CSharpFullMemberFormatter {
- protected override StringBuilder AppendNamespace (StringBuilder buf, Type type)
+ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReference type)
{
return buf;
}
}
class DocTypeMemberFormatter : DocTypeFullMemberFormatter {
- protected override StringBuilder AppendNamespace (StringBuilder buf, Type type)
+ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReference type)
{
return buf;
}
private bool AddTypeCount = true;
- protected override string GetTypeName (Type type)
- {
- return base.GetTypeName (type);
- }
+ private TypeReference genDeclType;
+ private MethodReference genDeclMethod;
- private Type genDeclType;
- private MethodBase genDeclMethod;
-
- protected override StringBuilder AppendTypeName (StringBuilder buf, Type type)
+ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReference type, DynamicParserContext context)
{
- if (DocUtils.IsGenericParameter (type)) {
+ if (type is GenericParameter) {
int l = buf.Length;
if (genDeclType != null) {
- Type[] genArgs = DocUtils.GetGenericArguments (genDeclType);
- for (int i = 0; i < genArgs.Length; ++i) {
+ IList<GenericParameter> genArgs = genDeclType.GenericParameters;
+ for (int i = 0; i < genArgs.Count; ++i) {
if (genArgs [i].Name == type.Name) {
buf.Append ('`').Append (i);
break;
}
}
if (genDeclMethod != null) {
- Type[] genArgs = null;
- if (DocUtils.GetContainsGenericParameters (genDeclMethod)) {
- genArgs = DocUtils.GetGenericArguments (genDeclMethod);
- }
- else
- genArgs = new Type[0];
- for (int i = 0; i < genArgs.Length; ++i) {
- if (genArgs [i].Name == type.Name) {
- buf.Append ("``").Append (i);
- break;
+ IList<GenericParameter> genArgs = null;
+ if (genDeclMethod.IsGenericMethod ()) {
+ genArgs = genDeclMethod.GenericParameters;
+ for (int i = 0; i < genArgs.Count; ++i) {
+ if (genArgs [i].Name == type.Name) {
+ buf.Append ("``").Append (i);
+ break;
+ }
}
}
}
}
}
else {
- base.AppendTypeName (buf, type);
+ base.AppendTypeName (buf, type, context);
if (AddTypeCount) {
- int numArgs = DocUtils.GetGenericArguments (type).Length;
+ int numArgs = type.GenericParameters.Count;
if (type.DeclaringType != null)
- numArgs -= DocUtils.GetGenericArguments (type).Length;
+ numArgs -= type.GenericParameters.Count;
if (numArgs > 0) {
buf.Append ('`').Append (numArgs);
}
return buf;
}
- protected override StringBuilder AppendGenericType (StringBuilder buf, Type type)
+ protected override StringBuilder AppendArrayModifiers (StringBuilder buf, ArrayType array)
+ {
+ buf.Append (ArrayDelimeters [0]);
+ int rank = array.Rank;
+ if (rank > 1) {
+ buf.Append ("0:");
+ for (int i = 1; i < rank; ++i) {
+ buf.Append (",0:");
+ }
+ }
+ return buf.Append (ArrayDelimeters [1]);
+ }
+
+ protected override StringBuilder AppendGenericType (StringBuilder buf, TypeReference type, DynamicParserContext context)
{
if (!AddTypeCount)
- base.AppendGenericType (buf, type);
+ base.AppendGenericType (buf, type, context);
else
- AppendType (buf, type);
+ AppendType (buf, type, context);
return buf;
}
- private StringBuilder AppendType (StringBuilder buf, Type type)
+ private StringBuilder AppendType (StringBuilder buf, TypeReference type, DynamicParserContext context)
{
- int numArgs = DocUtils.GetGenericArguments (type).Length;
- if (type.DeclaringType != null) {
- AppendType (buf, type.DeclaringType).Append (NestedTypeSeparator);
- numArgs -= DocUtils.GetGenericArguments (type.DeclaringType).Length;
- }
- base.AppendTypeName (buf, type);
- if (numArgs > 0) {
- buf.Append ('`').Append (numArgs);
+ List<TypeReference> decls = DocUtils.GetDeclaringTypes (type);
+ bool insertNested = false;
+ int prevParamCount = 0;
+ foreach (var decl in decls) {
+ if (insertNested)
+ buf.Append (NestedTypeSeparator);
+ insertNested = true;
+ base.AppendTypeName (buf, decl, context);
+ int argCount = DocUtils.GetGenericArgumentCount (decl);
+ int numArgs = argCount - prevParamCount;
+ prevParamCount = argCount;
+ if (numArgs > 0)
+ buf.Append ('`').Append (numArgs);
}
return buf;
}
- protected override string GetConstructorName (ConstructorInfo constructor)
+ public override string GetDeclaration (MemberReference member)
+ {
+ TypeReference r = member as TypeReference;
+ if (r != null) {
+ return "T:" + GetTypeName (r);
+ }
+ return base.GetDeclaration (member);
+ }
+
+ protected override string GetConstructorName (MethodReference constructor)
{
- return GetMethodBaseName (constructor, "#ctor");
+ return GetMethodDefinitionName (constructor, "#ctor");
}
- protected override string GetMethodName (MethodInfo method)
+ protected override string GetMethodName (MethodReference method)
{
string name = null;
- if (!DocUtils.IsExplicitlyImplemented (method))
+ MethodDefinition methodDef = method as MethodDefinition;
+ if (methodDef == null || !DocUtils.IsExplicitlyImplemented (methodDef))
name = method.Name;
else {
- Type iface;
- MethodInfo ifaceMethod;
- DocUtils.GetInfoForExplicitlyImplementedMethod (method, out iface, out ifaceMethod);
+ TypeReference iface;
+ MethodReference ifaceMethod;
+ DocUtils.GetInfoForExplicitlyImplementedMethod (methodDef, out iface, out ifaceMethod);
AddTypeCount = false;
name = GetTypeName (iface) + "." + ifaceMethod.Name;
AddTypeCount = true;
}
- return GetMethodBaseName (method, name);
+ return GetMethodDefinitionName (method, name);
}
- private string GetMethodBaseName (MethodBase method, string name)
+ private string GetMethodDefinitionName (MethodReference method, string name)
{
StringBuilder buf = new StringBuilder ();
buf.Append (GetTypeName (method.DeclaringType));
buf.Append ('.');
buf.Append (name.Replace (".", "#"));
- if (DocUtils.GetContainsGenericParameters (method)) {
- Type[] genArgs = DocUtils.GetGenericArguments (method);
- if (genArgs.Length > 0)
- buf.Append ("``").Append (genArgs.Length);
- }
- ParameterInfo[] parameters = method.GetParameters ();
- genDeclType = method.DeclaringType;
- genDeclMethod = method;
- AppendParameters (buf, DocUtils.GetGenericArguments (method.DeclaringType), parameters);
- genDeclType = null;
- genDeclMethod = null;
+ if (method.IsGenericMethod ()) {
+ IList<GenericParameter> genArgs = method.GenericParameters;
+ if (genArgs.Count > 0)
+ buf.Append ("``").Append (genArgs.Count);
+ }
+ IList<ParameterDefinition> parameters = method.Parameters;
+ try {
+ genDeclType = method.DeclaringType;
+ genDeclMethod = method;
+ AppendParameters (buf, method.DeclaringType.GenericParameters, parameters);
+ }
+ finally {
+ genDeclType = null;
+ genDeclMethod = null;
+ }
return buf.ToString ();
}
- private StringBuilder AppendParameters (StringBuilder buf, Type[] genArgs, ParameterInfo[] parameters)
+ private StringBuilder AppendParameters (StringBuilder buf, IList<GenericParameter> genArgs, IList<ParameterDefinition> parameters)
{
- if (parameters.Length == 0)
+ if (parameters.Count == 0)
return buf;
buf.Append ('(');
AppendParameter (buf, genArgs, parameters [0]);
- for (int i = 1; i < parameters.Length; ++i) {
+ for (int i = 1; i < parameters.Count; ++i) {
buf.Append (',');
AppendParameter (buf, genArgs, parameters [i]);
}
return buf.Append (')');
}
- private StringBuilder AppendParameter (StringBuilder buf, Type[] genArgs, ParameterInfo parameter)
+ private StringBuilder AppendParameter (StringBuilder buf, IList<GenericParameter> genArgs, ParameterDefinition parameter)
{
AddTypeCount = false;
buf.Append (GetTypeName (parameter.ParameterType));
return buf;
}
- protected override string GetPropertyName (PropertyInfo property)
+ protected override string GetPropertyName (PropertyReference property)
{
string name = null;
- MethodInfo method = property.GetGetMethod (true);
- if (method == null)
- method = property.GetSetMethod (true);
- if (!DocUtils.IsExplicitlyImplemented (method))
+ PropertyDefinition propertyDef = property as PropertyDefinition;
+ MethodDefinition method = null;
+ if (propertyDef != null)
+ method = propertyDef.GetMethod ?? propertyDef.SetMethod;
+ if (method != null && !DocUtils.IsExplicitlyImplemented (method))
name = property.Name;
else {
- Type iface;
- MethodInfo ifaceMethod;
+ TypeReference iface;
+ MethodReference ifaceMethod;
DocUtils.GetInfoForExplicitlyImplementedMethod (method, out iface, out ifaceMethod);
AddTypeCount = false;
name = string.Join ("#", new string[]{
buf.Append (GetName (property.DeclaringType));
buf.Append ('.');
buf.Append (name);
- ParameterInfo[] parameters = property.GetIndexParameters ();
- if (parameters.Length > 0) {
+ IList<ParameterDefinition> parameters = property.Parameters;
+ if (parameters.Count > 0) {
genDeclType = property.DeclaringType;
buf.Append ('(');
- Type[] genArgs = DocUtils.GetGenericArguments (property.DeclaringType);
+ IList<GenericParameter> genArgs = property.DeclaringType.GenericParameters;
AppendParameter (buf, genArgs, parameters [0]);
- for (int i = 1; i < parameters.Length; ++i) {
+ for (int i = 1; i < parameters.Count; ++i) {
buf.Append (',');
AppendParameter (buf, genArgs, parameters [i]);
}
return buf.ToString ();
}
- protected override string GetFieldName (FieldInfo field)
+ protected override string GetFieldName (FieldReference field)
{
return string.Format ("{0}.{1}",
GetName (field.DeclaringType), field.Name);
}
- protected override string GetEventName (EventInfo e)
+ protected override string GetEventName (EventReference e)
{
return string.Format ("{0}.{1}",
GetName (e.DeclaringType), e.Name);
}
- protected override string GetTypeDeclaration (Type type)
+ protected override string GetTypeDeclaration (TypeDefinition type)
{
string name = GetName (type);
if (type == null)
return "T:" + name;
}
- protected override string GetConstructorDeclaration (ConstructorInfo constructor)
+ protected override string GetConstructorDeclaration (MethodDefinition constructor)
{
string name = GetName (constructor);
if (name == null)
return "M:" + name;
}
- protected override string GetMethodDeclaration (MethodInfo method)
+ protected override string GetMethodDeclaration (MethodDefinition method)
{
string name = GetName (method);
if (name == null)
return "M:" + name;
}
- protected override string GetPropertyDeclaration (PropertyInfo property)
+ protected override string GetPropertyDeclaration (PropertyDefinition property)
{
string name = GetName (property);
if (name == null)
return "P:" + name;
}
- protected override string GetFieldDeclaration (FieldInfo field)
+ protected override string GetFieldDeclaration (FieldDefinition field)
{
string name = GetName (field);
if (name == null)
return "F:" + name;
}
- protected override string GetEventDeclaration (EventInfo e)
+ protected override string GetEventDeclaration (EventDefinition e)
{
string name = GetName (e);
if (name == null)
}
class FileNameMemberFormatter : SlashDocMemberFormatter {
- protected override StringBuilder AppendNamespace (StringBuilder buf, Type type)
+ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReference type)
{
return buf;
}