* Monodoc/ecma-provider.cs: Viewing type members (plural, e.g. the
[mono.git] / mcs / tools / mdoc / Mono.Documentation / monodocer.cs
index 1022e6db3db07b565fdc43e8fa662868be6d2c80..fe8c06a7cdc00d73e2add8590ff7de497a9dfba4 100644 (file)
@@ -5,6 +5,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Globalization;
 using System.IO;
 using System.Linq;
@@ -22,174 +23,150 @@ using StringToXmlNodeMap   = System.Collections.Generic.Dictionary<string, Syste
 
 namespace Mono.Documentation {
 
-class MDocUpdaterOptions 
-{
-       public string path = null;
-       public string updateto = null;
-       public List<string> assembly = null;
-       public List<string> type = null;
-       public string @namespace = null;
-       public bool delete = false;
-       public bool overrides = true;
-       public bool ignoremembers = false;
-       public bool ignore_extra_docs = false;
-       public string name;
-       public string import;
-       public bool pretty = true;
-       public string since;
-       public bool show_exceptions;
-}
-
 class MDocUpdater : MDocCommand
 {
+       string srcPath;
+       List<AssemblyDefinition> assemblies;
        
-       static string srcPath;
-       static List<AssemblyDefinition> assemblies;
+       bool delete;
+       bool show_exceptions;
+       bool no_assembly_versions;
+       ExceptionLocations? exceptions;
        
-       static bool nooverrides = true, delete = false, ignoremembers = false;
-       static bool pretty = false;
-       static bool show_exceptions = false;
-       
-       static int additions = 0, deletions = 0;
+       int additions = 0, deletions = 0;
 
-       static string name;
        static XmlDocument slashdocs;
-       static XmlReader ecmadocs;
+       XmlReader ecmadocs;
 
-       static string since;
+       string since;
 
-       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 ();
+       static readonly MemberFormatter csharpFullFormatter  = new CSharpFullMemberFormatter ();
+       static readonly MemberFormatter csharpFormatter      = new CSharpMemberFormatter ();
+       static readonly MemberFormatter docTypeFormatter     = new DocTypeMemberFormatter ();
+       static readonly MemberFormatter slashdocFormatter    = new SlashDocMemberFormatter ();
+       static readonly MemberFormatter filenameFormatter    = new FileNameMemberFormatter ();
 
-       static MyXmlNodeList extensionMethods = new MyXmlNodeList ();
+       MyXmlNodeList extensionMethods = new MyXmlNodeList ();
 
        public override void Run (IEnumerable<string> args)
        {
-               var opts = new MDocUpdaterOptions {
-                       overrides        = true,
-                       pretty           = true,
-                       show_exceptions  = DebugOutput,
-               };
-
-               opts.type = new List<string> ();
+               show_exceptions = DebugOutput;
+               string import = null;
+               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" +
+                               "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 "no-assembly-versions":
+                                                       no_assembly_versions = true;
+                                                       break;
+                                               default:
+                                                       throw new Exception ("Unsupported flag `" + v + "'.");
+                                       }
+                               } },
+                       { "fno-assembly-versions",
+                               "Do not generate //AssemblyVersion elements.",
+                               v => no_assembly_versions = v != null },
+                       { "i|import=", 
+                               "Import documentation from {FILE}.",
+                               v => import = v },
+                       { "o|out=",
+                               "Root {DIRECTORY} to generate/update documentation.",
+                               v => srcPath = 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 => opts.type.Add (v) },
+                               v => types.Add (v) },
                };
-               opts.assembly = Parse (p, args, "update", 
+               var assemblies = Parse (p, args, "update", 
                                "[OPTIONS]+ ASSEMBLIES",
                                "Create or update documentation from ASSEMBLIES.");
-               if (opts.assembly == null)
+               if (assemblies == null)
                        return;
-               if (opts.assembly.Count == 0)
+               if (assemblies.Count == 0)
                        Error ("No assemblies specified.");
 
-               Run (opts);
-               opts.name = ""; // remove warning about unused member
-       }
-
-       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;
-
-               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;
+               // PARSE BASIC OPTIONS AND LOAD THE ASSEMBLY TO DOCUMENT
+               
+               if (srcPath == null)
+                       throw new InvalidOperationException("The --out option is required.");
+               
+               this.assemblies = assemblies.Select (a => LoadAssembly (a)).ToList ();
 
-                       if (opts.type != null && opts.type.Count > 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 = opts.assembly.Select (a => LoadAssembly (a)).ToList ();
-
-                       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);
+               if (import != null && ecmadocs == null && slashdocs == null) {
+                       try {
+                               XmlReader r = new XmlTextReader (import);
+                               if (r.Read ()) {
+                                       while (r.NodeType != XmlNodeType.Element) {
+                                               if (!r.Read ())
+                                                       Error ("Unable to read XML file: {0}.", import);
+                                       }
+                                       if (r.LocalName == "doc") {
+                                               slashdocs = new XmlDocument();
+                                               slashdocs.Load (import);
+                                       }
+                                       else if (r.LocalName == "Libraries") {
+                                               ecmadocs = new XmlTextReader (import);
                                        }
-                                       r.Close ();
-                               } catch (Exception e) {
-                                       Error ("Could not load XML file: {0}", e.Message);
-                                       Environment.ExitCode = 1;
-                                       return;
+                                       else
+                                               Error ("Unsupported XML format within {0}.", import);
                                }
+                               r.Close ();
+                       } catch (Exception e) {
+                               Environment.ExitCode = 1;
+                               Error ("Could not load XML file: {0}.", e.Message);
                        }
-                       
-                       // PERFORM THE UPDATES
-                       
-                       string dest_dir = opts.updateto != null ? opts.updateto : opts.path;
-                       if (opts.type != null && opts.type.Count > 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);
-                       Environment.ExitCode = 1;
                }
+               
+               // PERFORM THE UPDATES
+               
+               if (types.Count > 0)
+                       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);
 
                Console.WriteLine("Members Added: {0}, Members Deleted: {1}", additions, deletions);
        }
 
-       private static new 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 "asm":     loc |= ExceptionLocations.Assembly; break;
+                               case "depasm":  loc |= ExceptionLocations.DependentAssemblies; break;
+                               case "all":     loc = ExceptionLocations.All; break;
+                               default:        throw new NotSupportedException ("Unsupported --exceptions value: " + type);
+                       }
+               }
+               return loc;
+       }
+
+       private void Warning (string format, params object[] args)
        {
-               Console.Error.Write ("monodocer: ");
-               Console.Error.WriteLine (format, args);
+               Message (TraceLevel.Warning, "mdoc: " + format, args);
        }
        
        private static AssemblyDefinition LoadAssembly (string name)
@@ -260,7 +237,8 @@ class MDocUpdater : MDocCommand
                }
        }
        
-       private static XmlDocument CreateIndexStub() {
+       private XmlDocument CreateIndexStub()
+       {
                XmlDocument index = new XmlDocument();
 
                XmlElement index_root = index.CreateElement("Overview");
@@ -310,7 +288,7 @@ class MDocUpdater : MDocCommand
                }
        }
 
-       public static void DoUpdateTypes (string basepath, List<string> typenames, string dest)
+       public void DoUpdateTypes (string basepath, List<string> typenames, string dest)
        {
                var found = new HashSet<string> ();
                foreach (AssemblyDefinition assembly in assemblies) {
@@ -325,10 +303,10 @@ class MDocUpdater : MDocCommand
                        throw new InvalidOperationException("Type(s) not found: " + string.Join (", ", notFound.ToArray ()));
        }
 
-       public static string DoUpdateType(TypeDefinition type, string basepath, string dest, XmlReader ecmaDocsType)
+       public string DoUpdateType (TypeDefinition type, string basepath, string dest, XmlReader ecmaDocsType)
        {
                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;
@@ -352,7 +330,6 @@ class MDocUpdater : MDocCommand
                if (file.Exists) {
                        // Update
                        XmlDocument basefile = new XmlDocument();
-                       if (!pretty) basefile.PreserveWhitespace = true;
                        try {
                                basefile.Load(typefile);
                        } catch (Exception e) {
@@ -375,13 +352,13 @@ class MDocUpdater : MDocCommand
                return reltypefile;
        }
 
-       public static void DoUpdateNS(string ns, string nspath, string outpath) {
+       public void DoUpdateNS (string ns, string nspath, string outpath)
+       {
                Dictionary<TypeDefinition, object> seenTypes = new Dictionary<TypeDefinition,object> ();
                AssemblyDefinition                  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);
@@ -393,7 +370,7 @@ class MDocUpdater : MDocCommand
                                GetTypeFileName (basefile.SelectSingleNode("Type/@FullName").InnerText);
                        TypeDefinition type = assembly.GetType(typename);
                        if (type == null) {
-                               Error ("Type no longer in assembly: " + typename);
+                               Warning ("Type no longer in assembly: " + typename);
                                continue;
                        }                       
 
@@ -451,7 +428,7 @@ class MDocUpdater : MDocCommand
                return filename.ToString ();
        }
 
-       private static void AddIndexAssembly (AssemblyDefinition assembly, XmlElement parent)
+       private void AddIndexAssembly (AssemblyDefinition assembly, XmlElement parent)
        {
                XmlElement index_assembly = parent.OwnerDocument.CreateElement("Assembly");
                index_assembly.SetAttribute ("Name", assembly.Name.Name);
@@ -460,7 +437,7 @@ class MDocUpdater : MDocCommand
                parent.AppendChild(index_assembly);
        }
 
-       private static void DoUpdateAssemblies (string source, string dest) 
+       private void DoUpdateAssemblies (string source, string dest) 
        {
                string indexfile = dest + "/index.xml";
                XmlDocument index;
@@ -475,14 +452,10 @@ class MDocUpdater : MDocCommand
                        index = CreateIndexStub();
                }
                
-               if (name == null) {
-                       string defaultTitle = "Untitled";
-                       if (assemblies.Count == 1)
-                               defaultTitle = assemblies[0].Name.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");
@@ -508,7 +481,7 @@ class MDocUpdater : MDocCommand
                
        private static char[] InvalidFilenameChars = {'\\', '/', ':', '*', '?', '"', '<', '>', '|'};
 
-       private static void DoUpdateAssembly (AssemblyDefinition assembly, XmlElement index_types, string source, string dest, HashSet<string> goodfiles) 
+       private void DoUpdateAssembly (AssemblyDefinition assembly, XmlElement index_types, string source, string dest, HashSet<string> goodfiles) 
        {
                foreach (DocsTypeInfo docTypeInfo in GetTypes (assembly, null)) {
                        TypeDefinition type = docTypeInfo.Type;
@@ -568,7 +541,7 @@ class MDocUpdater : MDocCommand
                }
        }
 
-       static IEnumerable<Mono.Documentation.MDocUpdater.DocsTypeInfo> GetTypes (AssemblyDefinition assembly, List<string> forTypes)
+       IEnumerable<Mono.Documentation.MDocUpdater.DocsTypeInfo> GetTypes (AssemblyDefinition assembly, List<string> forTypes)
        {
                HashSet<string> seen = null;
                if (forTypes != null)
@@ -651,9 +624,21 @@ class MDocUpdater : MDocCommand
        }
 
        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);
                }
        }
        
@@ -702,7 +687,7 @@ class MDocUpdater : MDocCommand
                return true;
        }
 
-       private static void CleanupFiles (string dest, HashSet<string> 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("*")) {
@@ -735,7 +720,7 @@ class MDocUpdater : MDocCommand
                );
        }
 
-       private static string[] GetAssemblyVersions ()
+       private string[] GetAssemblyVersions ()
        {
                return (from a in assemblies select GetAssemblyVersion (a)).ToArray ();
        }
@@ -754,7 +739,7 @@ class MDocUpdater : MDocCommand
                        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) {
@@ -795,7 +780,7 @@ class MDocUpdater : MDocCommand
 
        static readonly XmlNodeComparer DefaultExtensionMethodComparer = new ExtensionMethodComparer ();
                
-       public static void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition type, string output, bool insertSince, XmlReader ecmaDocsType)
+       public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition type, string output, bool insertSince, XmlReader ecmaDocsType)
        {
                Console.WriteLine(message + ": " + type.FullName);
                
@@ -814,7 +799,7 @@ class MDocUpdater : MDocCommand
 
                // 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)) {
                                XmlElement oldmember  = info.Node;
@@ -823,7 +808,7 @@ class MDocUpdater : MDocCommand
 
                                // 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)
@@ -842,7 +827,7 @@ class MDocUpdater : MDocCommand
                                        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;
                                }
                                
@@ -855,7 +840,7 @@ class MDocUpdater : MDocCommand
                                oldmember.ParentNode.RemoveChild (oldmember);
                }
                
-               if (!DocUtils.IsDelegate (type) && !ignoremembers) {
+               if (!DocUtils.IsDelegate (type)) {
                        XmlNode members = WriteElement (basefile.DocumentElement, "Members");
                        foreach (IMemberReference m in type.GetMembers()) {
                                if (m is TypeDefinition) continue;
@@ -864,10 +849,6 @@ class MDocUpdater : MDocCommand
                                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 );
@@ -919,7 +900,7 @@ class MDocUpdater : MDocCommand
                        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) {
@@ -947,7 +928,7 @@ class MDocUpdater : MDocCommand
                                        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;
                        }
@@ -956,12 +937,12 @@ class MDocUpdater : MDocCommand
                        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 IEnumerable<DocsNodeInfo> GetDocumentationMembers (XmlDocument basefile, TypeDefinition type, XmlReader ecmaDocsMembers)
+       private IEnumerable<DocsNodeInfo> GetDocumentationMembers (XmlDocument basefile, TypeDefinition type, XmlReader ecmaDocsMembers)
        {
                if (ecmaDocsMembers != null) {
                        int membersDepth = ecmaDocsMembers.Depth;
@@ -978,7 +959,7 @@ class MDocUpdater : MDocCommand
                                                if (oldmember == null) {
                                                        m = GetMember (type, dm);
                                                        if (m == null) {
-                                                               Error ("Could not import ECMA docs for `{0}'s `{1}': Member not found.",
+                                                               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;
@@ -1005,7 +986,7 @@ class MDocUpdater : MDocCommand
                                                else {
                                                        m = GetMember (type, new DocumentationMember (oldmember));
                                                        if (m == null) {
-                                                               Error ("Could not import ECMA docs for `{0}'s `{1}': Member not found.",
+                                                               Warning ("Could not import ECMA docs for `{0}'s `{1}': Member not found.",
                                                                                type.FullName, dm.MemberSignatures ["C#"]);
                                                                continue;
                                                        }
@@ -1041,19 +1022,19 @@ class MDocUpdater : MDocCommand
                }
        }
 
-       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++;
@@ -1148,25 +1129,6 @@ class MDocUpdater : MDocCommand
                return false;
        }
        
-       private static bool IsNew (IMemberReference m)
-       {
-               if (!nooverrides) return true;
-               if (m is MethodDefinition && !IsNew ((MethodDefinition)m)) return false;
-               if (m is PropertyDefinition && !IsNew (((PropertyDefinition)m).GetMethod)) return false;
-               if (m is PropertyDefinition && !IsNew (((PropertyDefinition)m).SetMethod)) return false;
-               if (m is EventDefinition && !IsNew (((EventDefinition)m).AddMethod)) return false;
-               if (m is EventDefinition && !IsNew (((EventDefinition)m).InvokeMethod)) return false;
-               if (m is EventDefinition && !IsNew (((EventDefinition)m).RemoveMethod)) return false;
-               return true;
-       }
-       
-       private static bool IsNew (MethodDefinition m)
-       {
-               if (m == null)
-                       return true;
-               return m.IsNewSlot;
-       }
-
        // UPDATE HELPER FUNCTIONS
 
        private static IMemberReference GetMember (TypeDefinition type, DocumentationMember member)
@@ -1349,7 +1311,7 @@ class MDocUpdater : MDocCommand
        
        // CREATE A STUB DOCUMENTATION FILE     
 
-       public static XmlElement StubType (TypeDefinition type, string output, XmlReader ecmaDocsType)
+       public XmlElement StubType (TypeDefinition type, string output, XmlReader ecmaDocsType)
        {
                string typesig = MakeTypeSignature(type);
                if (typesig == null) return null; // not publicly visible
@@ -1363,7 +1325,7 @@ class MDocUpdater : MDocCommand
                return root;
        }
 
-       private static XmlElement CreateSinceNode (XmlDocument doc)
+       private XmlElement CreateSinceNode (XmlDocument doc)
        {
                XmlElement s = doc.CreateElement ("since");
                s.SetAttribute ("version", since);
@@ -1372,7 +1334,7 @@ class MDocUpdater : MDocCommand
        
        // STUBBING/UPDATING FUNCTIONS
        
-       public static void UpdateType (XmlElement root, TypeDefinition type, XmlReader ecmaDocsType)
+       public void UpdateType (XmlElement root, TypeDefinition type, XmlReader ecmaDocsType)
        {
                root.SetAttribute("Name", GetDocTypeName (type));
                root.SetAttribute("FullName", GetDocTypeFullName (type));
@@ -1382,7 +1344,14 @@ class MDocUpdater : MDocCommand
                
                XmlElement ass = WriteElement(root, "AssemblyInfo");
                WriteElementText(ass, "AssemblyName", type.Module.Assembly.Name.Name);
-               UpdateAssemblyVersions(root, type, true);
+               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
@@ -1489,7 +1458,7 @@ class MDocUpdater : MDocCommand
                return l;
        }
 
-       private static void UpdateMember (DocsNodeInfo info)
+       private void UpdateMember (DocsNodeInfo info)
        {
                XmlElement me = (XmlElement) info.Node;
                IMemberReference mi = info.Member;
@@ -1498,7 +1467,12 @@ class MDocUpdater : MDocCommand
 
                WriteElementText(me, "MemberType", GetMemberType(mi));
                
-               UpdateAssemblyVersions(me, mi, true);
+               if (!no_assembly_versions) {
+                       UpdateAssemblyVersions (me, mi, true);
+               }
+               else {
+                       ClearElement (me, "AssemblyInfo");
+               }
                ICustomAttributeProvider p = mi as ICustomAttributeProvider;
                if (p != null)
                        MakeAttributes (me, p.CustomAttributes, false);
@@ -1534,7 +1508,7 @@ class MDocUpdater : MDocCommand
                "typeparam",
        };
 
-       private static void UpdateExtensionMethods (XmlElement e, DocsNodeInfo info)
+       private void UpdateExtensionMethods (XmlElement e, DocsNodeInfo info)
        {
                MethodDefinition me = info.Member as MethodDefinition;
                if (me == null)
@@ -1599,7 +1573,7 @@ class MDocUpdater : MDocCommand
        private static bool GetFieldConstValue (FieldDefinition field, out string value)
        {
                value = null;
-               TypeDefinition type = DocUtils.GetTypeDefinition (field.DeclaringType);
+               TypeDefinition type = field.DeclaringType.Resolve ();
                if (type != null && type.IsEnum) return false;
                
                if (type != null && type.IsGenericType ()) return false;
@@ -1690,7 +1664,7 @@ class MDocUpdater : MDocCommand
        
        // DOCUMENTATION HELPER FUNCTIONS
        
-       private static void MakeDocNode (DocsNodeInfo info)
+       private void MakeDocNode (DocsNodeInfo info)
        {
                List<GenericParameter> genericParams      = info.GenericParameters;
                ParameterDefinitionCollection parameters  = info.Parameters;
@@ -1738,6 +1712,10 @@ class MDocUpdater : MDocCommand
                if (addremarks)
                        WriteElementInitialText(e, "remarks", "To be added.");
 
+               if (exceptions.HasValue && info.Member != null) {
+                       UpdateExceptions (e, info.Member);
+               }
+
                if (info.EcmaDocs != null) {
                        XmlReader r = info.EcmaDocs;
                        int depth = r.Depth;
@@ -1754,8 +1732,11 @@ class MDocUpdater : MDocCommand
                                switch (r.Name) {
                                        case "param":
                                        case "typeparam": {
+                                               string name = r.GetAttribute ("name");
+                                               if (name == null)
+                                                       break;
                                                XmlNode doc = e.SelectSingleNode (
-                                                               r.Name + "[@name='" + r.GetAttribute ("name") + "']");
+                                                               r.Name + "[@name='" + name + "']");
                                                string value = r.ReadInnerXml ();
                                                if (doc != null)
                                                        doc.InnerXml = value.Replace ("\r", "");
@@ -1767,6 +1748,8 @@ class MDocUpdater : MDocCommand
                                        case "seealso": {
                                                string name = r.Name;
                                                string cref = r.GetAttribute ("cref");
+                                               if (cref == null)
+                                                       break;
                                                XmlNode doc = e.SelectSingleNode (
                                                                r.Name + "[@cref='" + cref + "']");
                                                string value = r.ReadInnerXml ().Replace ("\r", "");
@@ -1828,7 +1811,10 @@ class MDocUpdater : MDocCommand
                                        switch (child.Name) {
                                                case "param":
                                                case "typeparam": {
-                                                       XmlElement p2 = (XmlElement) e.SelectSingleNode (child.Name + "[@name='" + child.Attributes ["name"].Value + "']");
+                                                       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;
@@ -1836,7 +1822,10 @@ class MDocUpdater : MDocCommand
                                                case "altmember":
                                                case "exception":
                                                case "permission": {
-                                                       XmlElement a = (XmlElement) e.SelectSingleNode (child.Name + "[@cref='" + child.Attributes ["cref"].Value + "']");
+                                                       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);
@@ -1846,7 +1835,10 @@ class MDocUpdater : MDocCommand
                                                        break;
                                                }
                                                case "seealso": {
-                                                       XmlElement a = (XmlElement) e.SelectSingleNode ("altmember[@cref='" + child.Attributes ["cref"].Value + "']");
+                                                       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);
@@ -1892,7 +1884,7 @@ class MDocUpdater : MDocCommand
        }
        
 
-       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];
@@ -1934,20 +1926,20 @@ class MDocUpdater : MDocCommand
                                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);
                                        }
@@ -1992,6 +1984,54 @@ class MDocUpdater : MDocCommand
                                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, IMemberReference 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.
@@ -2070,7 +2110,7 @@ class MDocUpdater : MDocCommand
                "System.Runtime.CompilerServices.ExtensionAttribute",
        };
 
-       private static void MakeAttributes (XmlElement root, CustomAttributeCollection attributes, bool assemblyAttributes)
+       private void MakeAttributes (XmlElement root, CustomAttributeCollection attributes, bool assemblyAttributes)
        {
                if (attributes.Count == 0) {
                        ClearElement(root, "Attributes");
@@ -2088,7 +2128,7 @@ class MDocUpdater : MDocCommand
                                .OrderBy (ca => ca.Constructor.DeclaringType.FullName)) {
                        if (!attribute.Resolve ()) {
                                // skip?
-                               Error ("warning: could not resolve type {0}.",
+                               Warning ("warning: could not resolve type {0}.",
                                                attribute.Constructor.DeclaringType.FullName);
                        }
                        TypeDefinition attrType = attribute.Constructor.DeclaringType as TypeDefinition;
@@ -2150,7 +2190,7 @@ class MDocUpdater : MDocCommand
                        return "\"" + v.ToString () + "\"";
                if (v is Boolean)
                        return (bool)v ? "true" : "false";
-               TypeDefinition valueDef = DocUtils.GetTypeDefinition (valueType);
+               TypeDefinition valueDef = valueType.Resolve ();
                if (valueDef == null || !valueDef.IsEnum)
                        return v.ToString ();
                string typename = GetDocTypeFullName (valueType);
@@ -2178,7 +2218,7 @@ class MDocUpdater : MDocCommand
                        .ToDictionary (f => Convert.ToUInt64 (f.Constant), f => f.Name);
        }
        
-       private static void MakeParameters (XmlElement root, ParameterDefinitionCollection parameters)
+       private void MakeParameters (XmlElement root, ParameterDefinitionCollection parameters)
        {
                XmlElement e = WriteElement(root, "Parameters");
                e.RemoveAll();
@@ -2195,7 +2235,7 @@ class MDocUpdater : MDocCommand
                }
        }
        
-       private static void MakeTypeParameters (XmlElement root, GenericParameterCollection typeParams)
+       private void MakeTypeParameters (XmlElement root, GenericParameterCollection typeParams)
        {
                if (typeParams == null || typeParams.Count == 0) {
                        XmlElement f = (XmlElement) root.SelectSingleNode ("TypeParameters");
@@ -2235,7 +2275,7 @@ class MDocUpdater : MDocCommand
                        if ((attrs & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
                                AppendElementText (ce, "ParameterAttribute", "ReferenceTypeConstraint");
                        foreach (TypeReference c in constraints) {
-                               TypeDefinition cd = DocUtils.GetTypeDefinition (c);
+                               TypeDefinition cd = c.Resolve ();
                                AppendElementText (ce,
                                                (cd != null && cd.IsInterface) ? "InterfaceName" : "BaseTypeName",
                                                GetDocTypeFullName (c));
@@ -2243,7 +2283,7 @@ class MDocUpdater : MDocCommand
                }
        }
 
-       private static void MakeParameters (XmlElement root, IMemberReference mi)
+       private void MakeParameters (XmlElement root, IMemberReference mi)
        {
                if (mi is MethodDefinition && ((MethodDefinition) mi).IsConstructor)
                        MakeParameters (root, ((MethodDefinition)mi).Parameters);
@@ -2273,7 +2313,7 @@ class MDocUpdater : MDocCommand
                return GetDocTypeFullName (type).Replace ("@", "&");
        }
 
-       private static void MakeReturnValue(XmlElement root, TypeReference type, CustomAttributeCollection attributes) 
+       private void MakeReturnValue (XmlElement root, TypeReference type, CustomAttributeCollection attributes) 
        {
                XmlElement e = WriteElement(root, "ReturnValue");
                e.RemoveAll();
@@ -2282,7 +2322,7 @@ class MDocUpdater : MDocCommand
                        MakeAttributes(e, attributes, false);
        }
        
-       private static void MakeReturnValue (XmlElement root, IMemberReference mi)
+       private void MakeReturnValue (XmlElement root, IMemberReference mi)
        {
                if (mi is MethodDefinition && ((MethodDefinition) mi).IsConstructor)
                        return;
@@ -2298,7 +2338,8 @@ class MDocUpdater : MDocCommand
                        throw new ArgumentException(mi + " is a " + mi.GetType().FullName);
        }
        
-       private static XmlElement MakeMember(XmlDocument doc, DocsNodeInfo info) {
+       private XmlElement MakeMember(XmlDocument doc, DocsNodeInfo info)
+       {
                IMemberReference mi = info.Member;
                if (mi is TypeDefinition) return null;
 
@@ -2424,7 +2465,7 @@ class MDocUpdater : MDocCommand
                        SetMemberInfo (member);
                }
 
-               public void SetType (TypeDefinition type)
+               void SetType (TypeDefinition type)
                {
                        if (type == null)
                                throw new ArgumentNullException ("type");
@@ -2445,7 +2486,7 @@ class MDocUpdater : MDocCommand
                        SetSlashDocs (type);
                }
 
-               public void SetMemberInfo (IMemberReference member)
+               void SetMemberInfo (IMemberReference member)
                {
                        if (member == null)
                                throw new ArgumentNullException ("member");
@@ -2596,14 +2637,21 @@ static class CecilExtensions {
 
        public static IMemberReference GetMember (this TypeDefinition type, string member)
        {
-               return GetMembers (type, member).FirstOrDefault ();
+               return GetMembers (type, member).EnsureZeroOrOne ();
+       }
+
+       static T EnsureZeroOrOne<T> (this IEnumerable<T> source)
+       {
+               if (source.Count () > 1)
+                       throw new InvalidOperationException ("too many matches");
+               return source.FirstOrDefault ();
        }
 
        public static MethodDefinition GetMethod (this TypeDefinition type, string method)
        {
                return type.Methods.Cast<MethodDefinition> ()
                        .Where (m => m.Name == method)
-                       .FirstOrDefault ();
+                       .EnsureZeroOrOne ();
        }
 
        public static IEnumerable<IMemberReference> GetDefaultMembers (this TypeReference type)
@@ -2631,8 +2679,8 @@ static class CecilExtensions {
        public static TypeDefinition GetType (this AssemblyDefinition assembly, string type)
        {
                return GetTypes (assembly)
-                               .Where (td => td.FullName == type)
-                               .FirstOrDefault ();
+                       .Where (td => td.FullName == type)
+                       .EnsureZeroOrOne ();
        }
 
        public static bool IsGenericType (this TypeReference type)
@@ -2644,6 +2692,26 @@ static class CecilExtensions {
        {
                return method.GenericParameters.Count > 0;
        }
+
+       public static IMemberReference Resolve (this IMemberReference member)
+       {
+               EventReference er = member as EventReference;
+               if (er != null)
+                       return er.Resolve ();
+               FieldReference fr = member as FieldReference;
+               if (fr != null)
+                       return fr.Resolve ();
+               MethodReference mr = member as MethodReference;
+               if (mr != null)
+                       return mr.Resolve ();
+               PropertyReference pr = member as PropertyReference;
+               if (pr != null)
+                       return pr.Resolve ();
+               TypeReference tr = member as TypeReference;
+               if (tr != null)
+                       return tr.Resolve ();
+               throw new NotSupportedException ("Cannot find definition for " + member.ToString ());
+       }
 }
 
 static class DocUtils {
@@ -2764,34 +2832,12 @@ static class DocUtils {
                                : type.GenericParameters.Count;
        }
 
-       public static TypeDefinition GetTypeDefinition (TypeReference type)
-       {
-               // Remove generic instantiation info (so string comparison below works)
-               if (type is TypeSpecification)
-                       type = type.GetOriginalType ();
-               TypeDefinition typeDef = type as TypeDefinition;
-               if (typeDef == null && type.Module != null) {
-                       AssemblyNameReference r = type.Module.AssemblyReferences.Cast<AssemblyNameReference> ()
-                                       .Where (anr => anr.Name == type.Scope.Name)
-                                       .FirstOrDefault ();
-                       if (r != null) {
-                               AssemblyDefinition ad = type.Module.Assembly.Resolver.Resolve (r);
-                               if (ad != null) {
-                                       typeDef = ad.GetTypes()
-                                               .Where (t => t.FullName == type.FullName)
-                                               .FirstOrDefault ();
-                               }
-                       }
-               }
-               return typeDef;
-       }
-
        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 = GetTypeDefinition (iface) ?? iface;
+                       TypeReference lookup = iface.Resolve () ?? iface;
                        if (!inheritedInterfaces.Contains (GetQualifiedTypeName (lookup)))
                                userInterfaces.Add (iface);
                }
@@ -2811,12 +2857,12 @@ static class DocUtils {
                        if (t == null) return;
                        foreach (TypeReference r in t.Interfaces) {
                                inheritedInterfaces.Add (GetQualifiedTypeName (r));
-                               a (GetTypeDefinition (r));
+                               a (r.Resolve ());
                        }
                };
                TypeReference baseRef = type.BaseType;
                while (baseRef != null) {
-                       TypeDefinition baseDef = GetTypeDefinition (baseRef);
+                       TypeDefinition baseDef = baseRef.Resolve ();
                        if (baseDef != null) {
                                a (baseDef);
                                baseRef = baseDef.BaseType;
@@ -2825,7 +2871,7 @@ static class DocUtils {
                                baseRef = null;
                }
                foreach (TypeReference r in type.Interfaces)
-                       a (GetTypeDefinition (r));
+                       a (r.Resolve ());
                return inheritedInterfaces;
        }
 }
@@ -2894,24 +2940,30 @@ class DocumentationMember {
        }
 }
 
+public enum MemberFormatterState {
+       None,
+       WithinArray,
+       WithinGenericTypeContainer,
+}
+
 public abstract class MemberFormatter {
        public virtual string GetName (IMemberReference member)
        {
                TypeReference type = member as TypeReference;
                if (type != null)
                        return GetTypeName (type);
-               MethodDefinition method  = member as MethodDefinition;
-               if (method != null && method.IsConstructor)
+               MethodReference method  = member as MethodReference;
+               if (method != null && method.Name == ".ctor") // method.IsConstructor
                        return GetConstructorName (method);
                if (method != null)
                        return GetMethodName (method);
-               PropertyDefinition prop = member as PropertyDefinition;
+               PropertyReference prop = member as PropertyReference;
                if (prop != null)
                        return GetPropertyName (prop);
-               FieldDefinition field = member as FieldDefinition;
+               FieldReference field = member as FieldReference;
                if (field != null)
                        return GetFieldName (field);
-               EventDefinition e = member as EventDefinition;
+               EventReference e = member as EventReference;
                if (e != null)
                        return GetEventName (e);
                throw new NotSupportedException ("Can't handle: " +
@@ -2929,16 +2981,21 @@ public abstract class MemberFormatter {
                get {return new char[]{'[', ']'};}
        }
 
+       protected virtual MemberFormatterState MemberFormatterState { get; set; }
+
        protected StringBuilder _AppendTypeName (StringBuilder buf, TypeReference type)
        {
                if (type is ArrayType) {
                        TypeSpecification spec = type as TypeSpecification;
                        _AppendTypeName (buf, spec != null ? spec.ElementType : type.GetOriginalType ())
                                        .Append (ArrayDelimeters [0]);
+                       var origState = MemberFormatterState;
+                       MemberFormatterState = MemberFormatterState.WithinArray;
                        ArrayType array = (ArrayType) type;
                        int rank = array.Rank;
                        if (rank > 1)
                                buf.Append (new string (',', rank-1));
+                       MemberFormatterState = origState;
                        return buf.Append (ArrayDelimeters [1]);
                }
                if (type is ReferenceType) {
@@ -3026,7 +3083,7 @@ public abstract class MemberFormatter {
                int prev = 0;
                bool insertNested = false;
                foreach (var decl in decls) {
-                       TypeReference declDef = DocUtils.GetTypeDefinition (decl) ?? decl;
+                       TypeReference declDef = decl.Resolve () ?? decl;
                        if (insertNested) {
                                buf.Append (NestedTypeSeparator);
                        }
@@ -3037,9 +3094,12 @@ public abstract class MemberFormatter {
                        prev = ac;
                        if (c > 0) {
                                buf.Append (GenericTypeContainer [0]);
+                               var origState = MemberFormatterState;
+                               MemberFormatterState = MemberFormatterState.WithinGenericTypeContainer;
                                _AppendTypeName (buf, genArgs [argIdx++]);
                                for (int i = 1; i < c; ++i)
                                        _AppendTypeName (buf.Append (","), genArgs [argIdx++]);
+                               MemberFormatterState = origState;
                                buf.Append (GenericTypeContainer [1]);
                        }
                }
@@ -3062,33 +3122,35 @@ public abstract class MemberFormatter {
                return buf;
        }
 
-       protected virtual string GetConstructorName (MethodDefinition constructor)
+       protected virtual string GetConstructorName (MethodReference constructor)
        {
                return constructor.Name;
        }
 
-       protected virtual string GetMethodName (MethodDefinition method)
+       protected virtual string GetMethodName (MethodReference method)
        {
                return method.Name;
        }
 
-       protected virtual string GetPropertyName (PropertyDefinition property)
+       protected virtual string GetPropertyName (PropertyReference property)
        {
                return property.Name;
        }
 
-       protected virtual string GetFieldName (FieldDefinition field)
+       protected virtual string GetFieldName (FieldReference field)
        {
                return field.Name;
        }
 
-       protected virtual string GetEventName (EventDefinition e)
+       protected virtual string GetEventName (EventReference e)
        {
                return e.Name;
        }
 
        public virtual string GetDeclaration (IMemberReference member)
        {
+               if (member == null)
+                       throw new ArgumentNullException ("member");
                TypeDefinition type = member as TypeDefinition;
                if (type != null)
                        return GetTypeDeclaration (type);
@@ -3239,7 +3301,7 @@ class CSharpFullMemberFormatter : MemberFormatter {
        protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReference type)
        {
                if (type is GenericParameter)
-                       return buf.Append (type.Name);
+                       return AppendGenericParameterConstraints (buf, (GenericParameter) type).Append (type.Name);
                string t = type.FullName;
                if (!t.StartsWith ("System.")) {
                        return base.AppendTypeName (buf, type);
@@ -3252,6 +3314,20 @@ class CSharpFullMemberFormatter : MemberFormatter {
                return base.AppendTypeName (buf, type);
        }
 
+       private StringBuilder AppendGenericParameterConstraints (StringBuilder buf, GenericParameter type)
+       {
+               if (MemberFormatterState != MemberFormatterState.WithinGenericTypeContainer)
+                       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);
@@ -3362,11 +3438,15 @@ class CSharpFullMemberFormatter : MemberFormatter {
                        ConstraintCollection 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;
@@ -3713,7 +3793,7 @@ class SlashDocMemberFormatter : MemberFormatter {
        private bool AddTypeCount = true;
 
        private TypeReference genDeclType;
-       private MethodDefinition genDeclMethod;
+       private MethodReference genDeclMethod;
 
        protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReference type)
        {
@@ -3804,20 +3884,21 @@ class SlashDocMemberFormatter : MemberFormatter {
                return base.GetDeclaration (member);
        }
 
-       protected override string GetConstructorName (MethodDefinition constructor)
+       protected override string GetConstructorName (MethodReference constructor)
        {
                return GetMethodDefinitionName (constructor, "#ctor");
        }
 
-       protected override string GetMethodName (MethodDefinition 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 {
                        TypeReference iface;
                        MethodReference ifaceMethod;
-                       DocUtils.GetInfoForExplicitlyImplementedMethod (method, out iface, out ifaceMethod);
+                       DocUtils.GetInfoForExplicitlyImplementedMethod (methodDef, out iface, out ifaceMethod);
                        AddTypeCount = false;
                        name = GetTypeName (iface) + "." + ifaceMethod.Name;
                        AddTypeCount = true;
@@ -3825,7 +3906,7 @@ class SlashDocMemberFormatter : MemberFormatter {
                return GetMethodDefinitionName (method, name);
        }
 
-       private string GetMethodDefinitionName (MethodDefinition method, string name)
+       private string GetMethodDefinitionName (MethodReference method, string name)
        {
                StringBuilder buf = new StringBuilder ();
                buf.Append (GetTypeName (method.DeclaringType));
@@ -3837,11 +3918,15 @@ class SlashDocMemberFormatter : MemberFormatter {
                                buf.Append ("``").Append (genArgs.Count);
                }
                ParameterDefinitionCollection parameters = method.Parameters;
-               genDeclType = method.DeclaringType;
-               genDeclMethod = method;
-               AppendParameters (buf, method.DeclaringType.GenericParameters, parameters);
-               genDeclType = null;
-               genDeclMethod = null;
+               try {
+                       genDeclType   = method.DeclaringType;
+                       genDeclMethod = method;
+                       AppendParameters (buf, method.DeclaringType.GenericParameters, parameters);
+               }
+               finally {
+                       genDeclType   = null;
+                       genDeclMethod = null;
+               }
                return buf.ToString ();
        }
 
@@ -3869,14 +3954,15 @@ class SlashDocMemberFormatter : MemberFormatter {
                return buf;
        }
 
-       protected override string GetPropertyName (PropertyDefinition property)
+       protected override string GetPropertyName (PropertyReference property)
        {
                string name = null;
 
-               MethodDefinition method = property.GetMethod;
-               if (method == null)
-                       method = property.SetMethod;
-               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 {
                        TypeReference iface;
@@ -3910,13 +3996,13 @@ class SlashDocMemberFormatter : MemberFormatter {
                return buf.ToString ();
        }
 
-       protected override string GetFieldName (FieldDefinition field)
+       protected override string GetFieldName (FieldReference field)
        {
                return string.Format ("{0}.{1}",
                        GetName (field.DeclaringType), field.Name);
        }
 
-       protected override string GetEventName (EventDefinition e)
+       protected override string GetEventName (EventReference e)
        {
                return string.Format ("{0}.{1}",
                        GetName (e.DeclaringType), e.Name);