mcs/error recovery: handle errors caused by closing braces after a statement expressi...
[mono.git] / mcs / mcs / doc.cs
index e596bd1b9656e9db6650d108226663d4064d2d91..40edc1c9294ca935abf40eb4d73351af6fb9308e 100644 (file)
 //
 // doc.cs: Support for XML documentation comment.
 //
-// Author:
+// Authors:
 //     Atsushi Enomoto <atsushi@ximian.com>
+//  Marek Safar (marek.safar@gmail.com>
 //
-// Licensed under the terms of the GNU GPL
+// Dual licensed under the terms of the MIT X11 or GNU GPL
 //
-// (C) 2004 Novell, Inc.
+// Copyright 2004 Novell, Inc.
+// Copyright 2011 Xamarin Inc
 //
 //
-#if ! BOOTSTRAP_WITH_OLDLIB
+
 using System;
-using System.Collections;
-using System.Collections.Specialized;
+using System.Collections.Generic;
 using System.IO;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Permissions;
 using System.Text;
 using System.Xml;
+using System.Linq;
 
-using Mono.CompilerServices.SymbolWriter;
-
-namespace Mono.CSharp {
-
+namespace Mono.CSharp
+{
        //
-       // Support class for XML documentation.
+       // Implements XML documentation generation.
        //
-#if NET_2_0
-       static
-#else
-       abstract
-#endif
-       public class DocUtil
+       class DocumentationBuilder
        {
-#if !NET_2_0
-               private DocUtil () {}
-#endif
-               // TypeContainer
-
                //
-               // Generates xml doc comments (if any), and if required,
-               // handle warning report.
+               // Used to create element which helps well-formedness checking.
                //
-               internal static void GenerateTypeDocComment (TypeContainer t,
-                       DeclSpace ds)
-               {
-                       GenerateDocComment (t, ds);
-
-                       if (t.DefaultStaticConstructor != null)
-                               t.DefaultStaticConstructor.GenerateDocComment (t);
+               readonly XmlDocument XmlDocumentation;
 
-                       if (t.InstanceConstructors != null)
-                               foreach (Constructor c in t.InstanceConstructors)
-                                       c.GenerateDocComment (t);
+               readonly ModuleContainer module;
 
-                       if (t.Types != null)
-                               foreach (TypeContainer tc in t.Types)
-                                       tc.GenerateDocComment (t);
-
-                       if (t.Delegates != null)
-                               foreach (Delegate de in t.Delegates)
-                                       de.GenerateDocComment (t);
-                       if (t.Enums != null)
-                               foreach (Enum en in t.Enums)
-                                       en.GenerateDocComment (t);
+               //
+               // The output for XML documentation.
+               //
+               XmlWriter XmlCommentOutput;
 
-                       if (t.Constants != null)
-                               foreach (Const c in t.Constants)
-                                       c.GenerateDocComment (t);
+               static readonly string line_head = Environment.NewLine + "            ";
 
-                       if (t.Fields != null)
-                               foreach (FieldBase f in t.Fields)
-                                       f.GenerateDocComment (t);
+               //
+               // Stores XmlDocuments that are included in XML documentation.
+               // Keys are included filenames, values are XmlDocuments.
+               //
+               Dictionary<string, XmlDocument> StoredDocuments = new Dictionary<string, XmlDocument> ();
 
-                       if (t.Events != null)
-                               foreach (Event e in t.Events)
-                                       e.GenerateDocComment (t);
+               public DocumentationBuilder (ModuleContainer module)
+               {
+                       this.module = module;
+                       XmlDocumentation = new XmlDocument ();
+                       XmlDocumentation.PreserveWhitespace = false;
+               }
 
-                       if (t.Indexers != null)
-                               foreach (Indexer ix in t.Indexers)
-                                       ix.GenerateDocComment (t);
+               Report Report {
+                       get {
+                               return module.Compiler.Report;
+                       }
+               }
 
-                       if (t.Properties != null)
-                               foreach (Property p in t.Properties)
-                                       p.GenerateDocComment (t);
+               public MemberName ParsedName {
+                       get; set;
+               }
 
-                       if (t.Methods != null)
-                               foreach (Method m in t.Methods)
-                                       m.GenerateDocComment (t);
+               public List<DocumentationParameter> ParsedParameters {
+                       get; set;
+               }
 
-                       if (t.Operators != null)
-                               foreach (Operator o in t.Operators)
-                                       o.GenerateDocComment (t);
+               public TypeExpression ParsedBuiltinType {
+                       get; set;
                }
 
-               // MemberCore
-               private static readonly string lineHead =
-                       Environment.NewLine + "            ";
+               public Operator.OpType? ParsedOperator {
+                       get; set;
+               }
 
-               private static XmlNode GetDocCommentNode (MemberCore mc,
-                       string name)
+               XmlNode GetDocCommentNode (MemberCore mc, string name)
                {
                        // FIXME: It could be even optimizable as not
                        // to use XmlDocument. But anyways the nodes
                        // are not kept in memory.
-                       XmlDocument doc = RootContext.Documentation.XmlDocumentation;
+                       XmlDocument doc = XmlDocumentation;
                        try {
                                XmlElement el = doc.CreateElement ("member");
                                el.SetAttribute ("name", name);
@@ -128,13 +100,14 @@ namespace Mono.CSharp {
                                        if (s.Length > 0)
                                                split [j++] = s;
                                }
-                               el.InnerXml = lineHead + String.Join (
-                                       lineHead, split, 0, j);
+                               el.InnerXml = line_head + String.Join (
+                                       line_head, split, 0, j);
                                return el;
-                       } catch (XmlException ex) {
-                               Report.Warning (1570, 1, mc.Location, "XML comment on `{0}' has non-well-formed XML ({1})", name, ex.Message);
-                               XmlComment com = doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name));
-                               return com;
+                       } catch (Exception ex) {
+                               Report.Warning (1570, 1, mc.Location, "XML documentation comment on `{0}' is not well-formed XML markup ({1})",
+                                       mc.GetSignatureForError (), ex.Message);
+
+                               return doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name));
                        }
                }
 
@@ -142,79 +115,77 @@ namespace Mono.CSharp {
                // Generates xml doc comments (if any), and if required,
                // handle warning report.
                //
-               internal static void GenerateDocComment (MemberCore mc,
-                       DeclSpace ds)
+               internal void GenerateDocumentationForMember (MemberCore mc)
                {
-                       if (mc.DocComment != null) {
-                               string name = mc.GetDocCommentName (ds);
-
-                               XmlNode n = GetDocCommentNode (mc, name);
-
-                               XmlElement el = n as XmlElement;
-                               if (el != null) {
-                                       mc.OnGenerateDocComment (el);
-
-                                       // FIXME: it could be done with XmlReader
-                                       XmlNodeList nl = n.SelectNodes (".//include");
-                                       if (nl.Count > 0) {
-                                               // It could result in current node removal, so prepare another list to iterate.
-                                               ArrayList al = new ArrayList (nl.Count);
-                                               foreach (XmlNode inc in nl)
-                                                       al.Add (inc);
-                                               foreach (XmlElement inc in al)
-                                                       if (!HandleInclude (mc, inc))
-                                                               inc.ParentNode.RemoveChild (inc);
-                                       }
+                       string name = mc.DocCommentHeader + mc.GetSignatureForDocumentation ();
 
-                                       // FIXME: it could be done with XmlReader
-                                       DeclSpace dsTarget = mc as DeclSpace;
-                                       if (dsTarget == null)
-                                               dsTarget = ds;
-
-                                       foreach (XmlElement see in n.SelectNodes (".//see"))
-                                               HandleSee (mc, dsTarget, see);
-                                       foreach (XmlElement seealso in n.SelectNodes (".//seealso"))
-                                               HandleSeeAlso (mc, dsTarget, seealso);
-                                       foreach (XmlElement see in n.SelectNodes (".//exception"))
-                                               HandleException (mc, dsTarget, see);
+                       XmlNode n = GetDocCommentNode (mc, name);
+
+                       XmlElement el = n as XmlElement;
+                       if (el != null) {
+                               var pm = mc as IParametersMember;
+                               if (pm != null) {
+                                       CheckParametersComments (mc, pm, el);
                                }
 
-                               n.WriteTo (RootContext.Documentation.XmlCommentOutput);
-                       }
-                       else if (mc.IsExposedFromAssembly ()) {
-                               Constructor c = mc as Constructor;
-                               if (c == null || !c.IsDefault ())
-                                       Report.Warning (1591, 4, mc.Location,
-                                               "Missing XML comment for publicly visible type or member `{0}'", mc.GetSignatureForError ());
+                               // FIXME: it could be done with XmlReader
+                               XmlNodeList nl = n.SelectNodes (".//include");
+                               if (nl.Count > 0) {
+                                       // It could result in current node removal, so prepare another list to iterate.
+                                       var al = new List<XmlNode> (nl.Count);
+                                       foreach (XmlNode inc in nl)
+                                               al.Add (inc);
+                                       foreach (XmlElement inc in al)
+                                               if (!HandleInclude (mc, inc))
+                                                       inc.ParentNode.RemoveChild (inc);
+                               }
+
+                               // FIXME: it could be done with XmlReader
+                               var ds_target = mc as TypeContainer;
+                               if (ds_target == null)
+                                       ds_target = mc.Parent;
+
+                               foreach (XmlElement see in n.SelectNodes (".//see"))
+                                       HandleSee (mc, ds_target, see);
+                               foreach (XmlElement seealso in n.SelectNodes (".//seealso"))
+                                       HandleSeeAlso (mc, ds_target, seealso);
+                               foreach (XmlElement see in n.SelectNodes (".//exception"))
+                                       HandleException (mc, ds_target, see);
+                               foreach (XmlElement node in n.SelectNodes (".//typeparam"))
+                                       HandleTypeParam (mc, node);
+                               foreach (XmlElement node in n.SelectNodes (".//typeparamref"))
+                                       HandleTypeParamRef (mc, node);
                        }
+
+                       n.WriteTo (XmlCommentOutput);
                }
 
                //
                // Processes "include" element. Check included file and
                // embed the document content inside this documentation node.
                //
-               private static bool HandleInclude (MemberCore mc, XmlElement el)
+               bool HandleInclude (MemberCore mc, XmlElement el)
                {
-                       bool keepIncludeNode = false;
+                       bool keep_include_node = false;
                        string file = el.GetAttribute ("file");
                        string path = el.GetAttribute ("path");
                        if (file == "") {
                                Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `file' attribute");
                                el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
-                               keepIncludeNode = true;
+                               keep_include_node = true;
                        }
                        else if (path.Length == 0) {
                                Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `path' attribute");
                                el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
-                               keepIncludeNode = true;
+                               keep_include_node = true;
                        }
                        else {
-                               XmlDocument doc = RootContext.Documentation.StoredDocuments [file] as XmlDocument;
-                               if (doc == null) {
+                               XmlDocument doc;
+                               if (!StoredDocuments.TryGetValue (file, out doc)) {
                                        try {
                                                doc = new XmlDocument ();
                                                doc.Load (file);
-                                               RootContext.Documentation.StoredDocuments.Add (file, doc);
+                                               StoredDocuments.Add (file, doc);
                                        } catch (Exception) {
                                                el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (String.Format (" Badly formed XML in at comment file `{0}': cannot be included ", file)), el);
                                                Report.Warning (1592, 1, mc.Location, "Badly formed XML in included comments file -- `{0}'", file);
@@ -226,7 +197,7 @@ namespace Mono.CSharp {
                                                if (nl.Count == 0) {
                                                        el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" No matching elements were found for the include tag embedded here. "), el);
                                        
-                                                       keepIncludeNode = true;
+                                                       keep_include_node = true;
                                                }
                                                foreach (XmlNode n in nl)
                                                        el.ParentNode.InsertBefore (el.OwnerDocument.ImportNode (n, true), el);
@@ -236,14 +207,13 @@ namespace Mono.CSharp {
                                        }
                                }
                        }
-                       return keepIncludeNode;
+                       return keep_include_node;
                }
 
                //
                // Handles <see> elements.
                //
-               private static void HandleSee (MemberCore mc,
-                       DeclSpace ds, XmlElement see)
+               void HandleSee (MemberCore mc, TypeContainer ds, XmlElement see)
                {
                        HandleXrefCommon (mc, ds, see);
                }
@@ -251,8 +221,7 @@ namespace Mono.CSharp {
                //
                // Handles <seealso> elements.
                //
-               private static void HandleSeeAlso (MemberCore mc,
-                       DeclSpace ds, XmlElement seealso)
+               void HandleSeeAlso (MemberCore mc, TypeContainer ds, XmlElement seealso)
                {
                        HandleXrefCommon (mc, ds, seealso);
                }
@@ -260,636 +229,305 @@ namespace Mono.CSharp {
                //
                // Handles <exception> elements.
                //
-               private static void HandleException (MemberCore mc,
-                       DeclSpace ds, XmlElement seealso)
+               void HandleException (MemberCore mc, TypeContainer ds, XmlElement seealso)
                {
                        HandleXrefCommon (mc, ds, seealso);
                }
 
-               static readonly char [] wsChars =
-                       new char [] {' ', '\t', '\n', '\r'};
-
                //
-               // returns a full runtime type name from a name which might
-               // be C# specific type name.
+               // Handles <typeparam /> node
                //
-               private static Type FindDocumentedType (MemberCore mc, string name, DeclSpace ds, string cref)
+               void HandleTypeParam (MemberCore mc, XmlElement node)
                {
-                       bool isArray = false;
-                       string identifier = name;
-                       if (name [name.Length - 1] == ']') {
-                               string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
-                               if (tmp [tmp.Length - 1] == '[') {
-                                       identifier = tmp.Substring (0, tmp.Length - 1).Trim (wsChars);
-                                       isArray = true;
-                               }
-                       }
-                       Type t = FindDocumentedTypeNonArray (mc, identifier, ds, cref);
-                       if (t != null && isArray)
-                               t = Array.CreateInstance (t, 0).GetType ();
-                       return t;
-               }
+                       if (!node.HasAttribute ("name"))
+                               return;
 
-               private static Type FindDocumentedTypeNonArray (MemberCore mc, 
-                       string identifier, DeclSpace ds, string cref)
-               {
-                       switch (identifier) {
-                       case "int":
-                               return typeof (int);
-                       case "uint":
-                               return typeof (uint);
-                       case "short":
-                               return typeof (short);
-                       case "ushort":
-                               return typeof (ushort);
-                       case "long":
-                               return typeof (long);
-                       case "ulong":
-                               return typeof (ulong);
-                       case "float":
-                               return typeof (float);
-                       case "double":
-                               return typeof (double);
-                       case "char":
-                               return typeof (char);
-                       case "decimal":
-                               return typeof (decimal);
-                       case "byte":
-                               return typeof (byte);
-                       case "sbyte":
-                               return typeof (sbyte);
-                       case "object":
-                               return typeof (object);
-                       case "bool":
-                               return typeof (bool);
-                       case "string":
-                               return typeof (string);
-                       case "void":
-                               return typeof (void);
-                       }
-                       FullNamedExpression e = ds.LookupNamespaceOrType (identifier, mc.Location, false);
-                       if (e != null) {
-                               if (!(e is TypeExpr))
-                                       return null;
-                               return e.Type;
+                       string tp_name = node.GetAttribute ("name");
+                       if (mc.CurrentTypeParameters != null) {
+                               if (mc.CurrentTypeParameters.Find (tp_name) != null)
+                                       return;
                        }
-                       int index = identifier.LastIndexOf ('.');
-                       if (index < 0)
-                               return null;
-                       int warn;
-                       Type parent = FindDocumentedType (mc, identifier.Substring (0, index), ds, cref);
-                       if (parent == null)
-                               return null;
-                       // no need to detect warning 419 here
-                       return FindDocumentedMember (mc, parent,
-                               identifier.Substring (index + 1),
-                               null, ds, out warn, cref, false, null).Member as Type;
-               }
-
-               private static MemberInfo [] empty_member_infos =
-                       new MemberInfo [0];
-
-               private static MemberInfo [] FindMethodBase (Type type,
-                       BindingFlags bindingFlags, MethodSignature signature)
-               {
-                       MemberList ml = TypeManager.FindMembers (
-                               type,
-                               MemberTypes.Constructor | MemberTypes.Method | MemberTypes.Property | MemberTypes.Custom,
-                               bindingFlags,
-                               MethodSignature.method_signature_filter,
-                               signature);
-                       if (ml == null)
-                               return empty_member_infos;
-
-                       return FilterOverridenMembersOut ((MemberInfo []) ml);
+                       
+                       // TODO: CS1710, CS1712
+                       
+                       mc.Compiler.Report.Warning (1711, 2, mc.Location,
+                               "XML comment on `{0}' has a typeparam name `{1}' but there is no type parameter by that name",
+                               mc.GetSignatureForError (), tp_name);
                }
 
-               static bool IsOverride (PropertyInfo deriv_prop, PropertyInfo base_prop)
+               //
+               // Handles <typeparamref /> node
+               //
+               void HandleTypeParamRef (MemberCore mc, XmlElement node)
                {
-                       if (!Invocation.IsAncestralType (base_prop.DeclaringType, deriv_prop.DeclaringType))
-                               return false;
-
-                       Type [] deriv_pd = TypeManager.GetArgumentTypes (deriv_prop);
-                       Type [] base_pd = TypeManager.GetArgumentTypes (base_prop);
-               
-                       if (deriv_pd.Length != base_pd.Length)
-                               return false;
-
-                       for (int j = 0; j < deriv_pd.Length; ++j) {
-                               if (deriv_pd [j] != base_pd [j])
-                                       return false;
-                               Type ct = TypeManager.TypeToCoreType (deriv_pd [j]);
-                               Type bt = TypeManager.TypeToCoreType (base_pd [j]);
-
-                               if (ct != bt)
-                                       return false;
-                       }
-
-                       return true;
-               }
+                       if (!node.HasAttribute ("name"))
+                               return;
 
-               private static MemberInfo [] FilterOverridenMembersOut (
-                       MemberInfo [] ml)
-               {
-                       if (ml == null)
-                               return empty_member_infos;
-
-                       ArrayList al = new ArrayList (ml.Length);
-                       for (int i = 0; i < ml.Length; i++) {
-                               MethodBase mx = ml [i] as MethodBase;
-                               PropertyInfo px = ml [i] as PropertyInfo;
-                               if (mx != null || px != null) {
-                                       bool overriden = false;
-                                       for (int j = 0; j < ml.Length; j++) {
-                                               if (j == i)
-                                                       continue;
-                                               MethodBase my = ml [j] as MethodBase;
-                                               if (mx != null && my != null &&
-                                                       Invocation.IsOverride (my, mx)) {
-                                                       overriden = true;
-                                                       break;
-                                               }
-                                               else if (mx != null)
-                                                       continue;
-                                               PropertyInfo py = ml [j] as PropertyInfo;
-                                               if (px != null && py != null &&
-                                                       IsOverride (py, px)) {
-                                                       overriden = true;
-                                                       break;
-                                               }
-                                       }
-                                       if (overriden)
-                                               continue;
+                       string tp_name = node.GetAttribute ("name");
+                       var member = mc;
+                       do {
+                               if (member.CurrentTypeParameters != null) {
+                                       if (member.CurrentTypeParameters.Find (tp_name) != null)
+                                               return;
                                }
-                               al.Add (ml [i]);
-                       }
-                       return al.ToArray (typeof (MemberInfo)) as MemberInfo [];
-               }
-
-               struct FoundMember
-               {
-                       public static FoundMember Empty = new FoundMember (true);
 
-                       public bool IsEmpty;
-                       public readonly MemberInfo Member;
-                       public readonly Type Type;
+                               member = member.Parent;
+                       } while (member != null);
 
-                       public FoundMember (bool regardlessOfThisValueItsEmpty)
-                       {
-                               IsEmpty = true;
-                               Member = null;
-                               Type = null;
-                       }
-
-                       public FoundMember (Type foundType, MemberInfo member)
-                       {
-                               IsEmpty = false;
-                               Type = foundType;
-                               Member = member;
-                       }
-               }
-
-               //
-               // Returns a MemberInfo that is referenced in XML documentation
-               // (by "see" or "seealso" elements).
-               //
-               private static FoundMember FindDocumentedMember (MemberCore mc,
-                       Type type, string memberName, Type [] paramList, 
-                       DeclSpace ds, out int warningType, string cref,
-                       bool warn419, string nameForError)
-               {
-                       for (; type != null; type = type.DeclaringType) {
-                               MemberInfo mi = FindDocumentedMemberNoNest (
-                                       mc, type, memberName, paramList, ds,
-                                       out warningType, cref, warn419,
-                                       nameForError);
-                               if (mi != null)
-                                       return new FoundMember (type, mi);
-                       }
-                       warningType = 0;
-                       return FoundMember.Empty;
+                       mc.Compiler.Report.Warning (1735, 2, mc.Location,
+                               "XML comment on `{0}' has a typeparamref name `{1}' that could not be resolved",
+                               mc.GetSignatureForError (), tp_name);
                }
 
-               private static MemberInfo FindDocumentedMemberNoNest (
-                       MemberCore mc, Type type, string memberName,
-                       Type [] paramList, DeclSpace ds, out int warningType, 
-                       string cref, bool warn419, string nameForError)
+               FullNamedExpression ResolveMemberName (IMemberContext context, MemberName mn)
                {
-                       warningType = 0;
-                       MemberInfo [] mis;
-
-                       if (paramList == null) {
-                               // search for fields/events etc.
-                               mis = TypeManager.MemberLookup (type, null,
-                                       type, MemberTypes.All,
-                                       BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
-                                       memberName, null);
-                               mis = FilterOverridenMembersOut (mis);
-                               if (mis == null || mis.Length == 0)
-                                       return null;
-                               if (warn419 && IsAmbiguous (mis))
-                                       Report419 (mc, nameForError, mis);
-                               return mis [0];
-                       }
+                       if (mn.Left == null)
+                               return context.LookupNamespaceOrType (mn.Name, mn.Arity, LookupMode.Probing, Location.Null);
 
-                       MethodSignature msig = new MethodSignature (memberName, null, paramList);
-                       mis = FindMethodBase (type, 
-                               BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
-                               msig);
+                       var left = ResolveMemberName (context, mn.Left);
+                       var ns = left as Namespace;
+                       if (ns != null)
+                               return ns.LookupTypeOrNamespace (context, mn.Name, mn.Arity, LookupMode.Probing, Location.Null);
 
-                       if (warn419 && mis.Length > 0) {
-                               if (IsAmbiguous (mis))
-                                       Report419 (mc, nameForError, mis);
-                               return mis [0];
-                       }
+                       TypeExpr texpr = left as TypeExpr;
+                       if (texpr != null) {
+                               var found = MemberCache.FindNestedType (texpr.Type, ParsedName.Name, ParsedName.Arity);
+                               if (found != null)
+                                       return new TypeExpression (found, Location.Null);
 
-                       // search for operators (whose parameters exactly
-                       // matches with the list) and possibly report CS1581.
-                       string oper = null;
-                       string returnTypeName = null;
-                       if (memberName.StartsWith ("implicit operator ")) {
-                               oper = "op_Implicit";
-                               returnTypeName = memberName.Substring (18).Trim (wsChars);
-                       }
-                       else if (memberName.StartsWith ("explicit operator ")) {
-                               oper = "op_Explicit";
-                               returnTypeName = memberName.Substring (18).Trim (wsChars);
-                       }
-                       else if (memberName.StartsWith ("operator ")) {
-                               oper = memberName.Substring (9).Trim (wsChars);
-                               switch (oper) {
-                               // either unary or binary
-                               case "+":
-                                       oper = paramList.Length == 2 ?
-                                               Binary.oper_names [(int) Binary.Operator.Addition] :
-                                               Unary.oper_names [(int) Unary.Operator.UnaryPlus];
-                                       break;
-                               case "-":
-                                       oper = paramList.Length == 2 ?
-                                               Binary.oper_names [(int) Binary.Operator.Subtraction] :
-                                               Unary.oper_names [(int) Unary.Operator.UnaryNegation];
-                                       break;
-                               // unary
-                               case "!":
-                                       oper = Unary.oper_names [(int) Unary.Operator.LogicalNot]; break;
-                               case "~":
-                                       oper = Unary.oper_names [(int) Unary.Operator.OnesComplement]; break;
-                                       
-                               case "++":
-                                       oper = "op_Increment"; break;
-                               case "--":
-                                       oper = "op_Decrement"; break;
-                               case "true":
-                                       oper = "op_True"; break;
-                               case "false":
-                                       oper = "op_False"; break;
-                               // binary
-                               case "*":
-                                       oper = Binary.oper_names [(int) Binary.Operator.Multiply]; break;
-                               case "/":
-                                       oper = Binary.oper_names [(int) Binary.Operator.Division]; break;
-                               case "%":
-                                       oper = Binary.oper_names [(int) Binary.Operator.Modulus]; break;
-                               case "&":
-                                       oper = Binary.oper_names [(int) Binary.Operator.BitwiseAnd]; break;
-                               case "|":
-                                       oper = Binary.oper_names [(int) Binary.Operator.BitwiseOr]; break;
-                               case "^":
-                                       oper = Binary.oper_names [(int) Binary.Operator.ExclusiveOr]; break;
-                               case "<<":
-                                       oper = Binary.oper_names [(int) Binary.Operator.LeftShift]; break;
-                               case ">>":
-                                       oper = Binary.oper_names [(int) Binary.Operator.RightShift]; break;
-                               case "==":
-                                       oper = Binary.oper_names [(int) Binary.Operator.Equality]; break;
-                               case "!=":
-                                       oper = Binary.oper_names [(int) Binary.Operator.Inequality]; break;
-                               case "<":
-                                       oper = Binary.oper_names [(int) Binary.Operator.LessThan]; break;
-                               case ">":
-                                       oper = Binary.oper_names [(int) Binary.Operator.GreaterThan]; break;
-                               case "<=":
-                                       oper = Binary.oper_names [(int) Binary.Operator.LessThanOrEqual]; break;
-                               case ">=":
-                                       oper = Binary.oper_names [(int) Binary.Operator.GreaterThanOrEqual]; break;
-                               default:
-                                       warningType = 1584;
-                                       Report.Warning (1020, 1, mc.Location, "Overloadable {0} operator is expected", paramList.Length == 2 ? "binary" : "unary");
-                                       Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'",
-                                               mc.GetSignatureForError (), cref);
-                                       return null;
-                               }
-                       }
-                       // here we still don't consider return type (to
-                       // detect CS1581 or CS1002+CS1584).
-                       msig = new MethodSignature (oper, null, paramList);
-
-                       mis = FindMethodBase (type, 
-                               BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
-                               msig);
-                       if (mis.Length == 0)
-                               return null; // CS1574
-                       MemberInfo mi = mis [0];
-                       Type expected = mi is MethodInfo ?
-                               ((MethodInfo) mi).ReturnType :
-                               mi is PropertyInfo ?
-                               ((PropertyInfo) mi).PropertyType :
-                               null;
-                       if (returnTypeName != null) {
-                               Type returnType = FindDocumentedType (mc, returnTypeName, ds, cref);
-                               if (returnType == null || returnType != expected) {
-                                       warningType = 1581;
-                                       Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute `{0}'", cref);
-                                       return null;
-                               }
+                               return null;
                        }
-                       return mis [0];
-               }
 
-               private static bool IsAmbiguous (MemberInfo [] members)
-               {
-                       if (members.Length < 2)
-                               return false;
-                       if (members.Length > 2)
-                               return true;
-                       if (members [0] is EventInfo && members [1] is FieldInfo)
-                               return false;
-                       if (members [1] is EventInfo && members [0] is FieldInfo)
-                               return false;
-                       return true;
+                       return left;
                }
 
                //
-               // Processes "see" or "seealso" elements.
-               // Checks cref attribute.
+               // Processes "see" or "seealso" elements from cref attribute.
                //
-               private static void HandleXrefCommon (MemberCore mc,
-                       DeclSpace ds, XmlElement xref)
+               void HandleXrefCommon (MemberCore mc, TypeContainer ds, XmlElement xref)
                {
-                       string cref = xref.GetAttribute ("cref").Trim (wsChars);
+                       string cref = xref.GetAttribute ("cref");
                        // when, XmlReader, "if (cref == null)"
                        if (!xref.HasAttribute ("cref"))
                                return;
-                       if (cref.Length == 0)
-                               Report.Warning (1001, 1, mc.Location, "Identifier expected");
-                               // ... and continue until CS1584.
-
-                       string signature; // "x:" are stripped
-                       string name; // method invokation "(...)" are removed
-                       string parameters; // method parameter list
 
-                       // strip 'T:' 'M:' 'F:' 'P:' 'E:' etc.
-                       // Here, MS ignores its member kind. No idea why.
+                       // Nothing to be resolved the reference is marked explicitly
                        if (cref.Length > 2 && cref [1] == ':')
-                               signature = cref.Substring (2).Trim (wsChars);
-                       else
-                               signature = cref;
-
-                       int parensPos = signature.IndexOf ('(');
-                       int bracePos = parensPos >= 0 ? -1 :
-                               signature.IndexOf ('[');
-                       if (parensPos > 0 && signature [signature.Length - 1] == ')') {
-                               name = signature.Substring (0, parensPos).Trim (wsChars);
-                               parameters = signature.Substring (parensPos + 1, signature.Length - parensPos - 2).Trim (wsChars);
-                       }
-                       else if (bracePos > 0 && signature [signature.Length - 1] == ']') {
-                               name = signature.Substring (0, bracePos).Trim (wsChars);
-                               parameters = signature.Substring (bracePos + 1, signature.Length - bracePos - 2).Trim (wsChars);
-                       }
-                       else {
-                               name = signature;
-                               parameters = null;
-                       }
-                       Normalize (mc, ref name);
-
-                       string identifier = GetBodyIdentifierFromName (name);
-
-                       // Check if identifier is valid.
-                       // This check is not necessary to mark as error, but
-                       // csc specially reports CS1584 for wrong identifiers.
-                       string [] nameElems = identifier.Split ('.');
-                       for (int i = 0; i < nameElems.Length; i++) {
-                               string nameElem = GetBodyIdentifierFromName (nameElems [i]);
-                               if (i > 0)
-                                       Normalize (mc, ref nameElem);
-                               if (!Tokenizer.IsValidIdentifier (nameElem)
-                                       && nameElem.IndexOf ("operator") < 0) {
-                                       Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'",
-                                               mc.GetSignatureForError (), cref);
-                                       xref.SetAttribute ("cref", "!:" + signature);
-                                       return;
-                               }
+                               return;
+
+                       // Additional symbols for < and > are allowed for easier XML typing
+                       cref = cref.Replace ('{', '<').Replace ('}', '>');
+
+                       var encoding = module.Compiler.Settings.Encoding;
+                       var s = new MemoryStream (encoding.GetBytes (cref));
+                       SeekableStreamReader seekable = new SeekableStreamReader (s, encoding);
+
+                       var source_file = new CompilationSourceFile ("{documentation}", "", 1);
+                       var doc_module = new ModuleContainer (module.Compiler);
+                       doc_module.DocumentationBuilder = this;
+                       source_file.NamespaceContainer = new NamespaceContainer (null, doc_module, null, source_file);
+
+                       Report parse_report = new Report (new NullReportPrinter ());
+                       var parser = new CSharpParser (seekable, source_file, parse_report);
+                       ParsedParameters = null;
+                       ParsedName = null;
+                       ParsedBuiltinType = null;
+                       ParsedOperator = null;
+                       parser.Lexer.putback_char = Tokenizer.DocumentationXref;
+                       parser.Lexer.parsing_generic_declaration_doc = true;
+                       parser.parse ();
+                       if (parse_report.Errors > 0) {
+                               Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'",
+                                       mc.GetSignatureForError (), cref);
+
+                               xref.SetAttribute ("cref", "!:" + cref);
+                               return;
                        }
 
-                       // check if parameters are valid
-                       Type [] parameterTypes;
-                       if (parameters == null)
-                               parameterTypes = null;
-                       else if (parameters.Length == 0)
-                               parameterTypes = Type.EmptyTypes;
-                       else {
-                               string [] paramList = parameters.Split (',');
-                               ArrayList plist = new ArrayList ();
-                               for (int i = 0; i < paramList.Length; i++) {
-                                       string paramTypeName = paramList [i].Trim (wsChars);
-                                       Normalize (mc, ref paramTypeName);
-                                       Type paramType = FindDocumentedType (mc, paramTypeName, ds, cref);
-                                       if (paramType == null) {
-                                               Report.Warning (1580, 1, mc.Location, "Invalid type for parameter `{0}' in XML comment cref attribute `{1}'",
-                                                       (i + 1).ToString (), cref);
-                                               return;
+                       MemberSpec member;
+                       string prefix = null;
+                       FullNamedExpression fne = null;
+
+                       //
+                       // Try built-in type first because we are using ParsedName as identifier of
+                       // member names on built-in types
+                       //
+                       if (ParsedBuiltinType != null && (ParsedParameters == null || ParsedName != null)) {
+                               member = ParsedBuiltinType.Type;
+                       } else {
+                               member = null;
+                       }
+
+                       if (ParsedName != null || ParsedOperator.HasValue) {
+                               TypeSpec type = null;
+                               string member_name = null;
+
+                               if (member == null) {
+                                       if (ParsedOperator.HasValue) {
+                                               type = mc.CurrentType;
+                                       } else if (ParsedName.Left != null) {
+                                               fne = ResolveMemberName (mc, ParsedName.Left);
+                                               if (fne != null) {
+                                                       var ns = fne as Namespace;
+                                                       if (ns != null) {
+                                                               fne = ns.LookupTypeOrNamespace (mc, ParsedName.Name, ParsedName.Arity, LookupMode.Probing, Location.Null);
+                                                               if (fne != null) {
+                                                                       member = fne.Type;
+                                                               }
+                                                       } else {
+                                                               type = fne.Type;
+                                                       }
+                                               }
+                                       } else {
+                                               fne = ResolveMemberName (mc, ParsedName);
+                                               if (fne == null) {
+                                                       type = mc.CurrentType;
+                                               } else if (ParsedParameters == null) {
+                                                       member = fne.Type;
+                                               } else if (fne.Type.MemberDefinition == mc.CurrentType.MemberDefinition) {
+                                                       member_name = Constructor.ConstructorName;
+                                                       type = fne.Type;
+                                               }
                                        }
-                                       plist.Add (paramType);
+                               } else {
+                                       type = (TypeSpec) member;
+                                       member = null;
                                }
-                               parameterTypes = plist.ToArray (typeof (Type)) as Type [];
-                       }
 
-                       Type type = FindDocumentedType (mc, name, ds, cref);
-                       if (type != null
-                               // delegate must not be referenced with args
-                               && (!type.IsSubclassOf (typeof (System.Delegate))
-                               || parameterTypes == null)) {
-                               string result = GetSignatureForDoc (type)
-                                       + (bracePos < 0 ? String.Empty : signature.Substring (bracePos));
-                               xref.SetAttribute ("cref", "T:" + result);
-                               return; // a type
-                       }
+                               if (ParsedParameters != null) {
+                                       var old_printer = mc.Module.Compiler.Report.SetPrinter (new NullReportPrinter ());
+                                       foreach (var pp in ParsedParameters) {
+                                               pp.Resolve (mc);
+                                       }
+                                       mc.Module.Compiler.Report.SetPrinter (old_printer);
+                               }
 
-                       int period = name.LastIndexOf ('.');
-                       if (period > 0) {
-                               string typeName = name.Substring (0, period);
-                               string memberName = name.Substring (period + 1);
-                               Normalize (mc, ref memberName);
-                               type = FindDocumentedType (mc, typeName, ds, cref);
-                               int warnResult;
                                if (type != null) {
-                                       FoundMember fm = FindDocumentedMember (mc, type, memberName, parameterTypes, ds, out warnResult, cref, true, name);
-                                       if (warnResult > 0)
-                                               return;
-                                       if (!fm.IsEmpty) {
-                                               MemberInfo mi = fm.Member;
-                                               // we cannot use 'type' directly
-                                               // to get its name, since mi
-                                               // could be from DeclaringType
-                                               // for nested types.
-                                               xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + GetSignatureForDoc (fm.Type) + "." + memberName + GetParametersFormatted (mi));
-                                               return; // a member of a type
+                                       if (member_name == null)
+                                               member_name = ParsedOperator.HasValue ?
+                                                       Operator.GetMetadataName (ParsedOperator.Value) : ParsedName.Name;
+
+                                       int parsed_param_count;
+                                       if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) {
+                                               parsed_param_count = ParsedParameters.Count - 1;
+                                       } else if (ParsedParameters != null) {
+                                               parsed_param_count = ParsedParameters.Count;
+                                       } else {
+                                               parsed_param_count = 0;
                                        }
-                               }
-                       }
-                       else {
-                               int warnResult;
-                               FoundMember fm = FindDocumentedMember (mc, ds.TypeBuilder, name, parameterTypes, ds, out warnResult, cref, true, name);
-                               if (warnResult > 0)
-                                       return;
-                               if (!fm.IsEmpty) {
-                                       MemberInfo mi = fm.Member;
-                                       // we cannot use 'type' directly
-                                       // to get its name, since mi
-                                       // could be from DeclaringType
-                                       // for nested types.
-                                       xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + GetSignatureForDoc (fm.Type) + "." + name + GetParametersFormatted (mi));
-                                       return; // local member name
-                               }
-                       }
 
-                       // It still might be part of namespace name.
-                       Namespace ns = ds.NamespaceEntry.NS.GetNamespace (name, false);
-                       if (ns != null) {
-                               xref.SetAttribute ("cref", "N:" + ns.FullName);
-                               return; // a namespace
-                       }
-                       if (RootNamespace.Global.IsNamespace (name)) {
-                               xref.SetAttribute ("cref", "N:" + name);
-                               return; // a namespace
-                       }
+                                       int parameters_match = -1;
+                                       do {
+                                               var members = MemberCache.FindMembers (type, member_name, true);
+                                               if (members != null) {
+                                                       foreach (var m in members) {
+                                                               if (ParsedName != null && m.Arity != ParsedName.Arity)
+                                                                       continue;
+
+                                                               if (ParsedParameters != null) {
+                                                                       IParametersMember pm = m as IParametersMember;
+                                                                       if (pm == null)
+                                                                               continue;
+
+                                                                       if (m.Kind == MemberKind.Operator && !ParsedOperator.HasValue)
+                                                                               continue;
+
+                                                                       int i;
+                                                                       for (i = 0; i < parsed_param_count; ++i) {
+                                                                               var pparam = ParsedParameters[i];
+
+                                                                               if (i >= pm.Parameters.Count || pparam == null ||
+                                                                                       pparam.TypeSpec != pm.Parameters.Types[i] ||
+                                                                                       (pparam.Modifier & Parameter.Modifier.SignatureMask) != (pm.Parameters.FixedParameters[i].ModFlags & Parameter.Modifier.SignatureMask)) {
+
+                                                                                       if (i > parameters_match) {
+                                                                                               parameters_match = i;
+                                                                                       }
+
+                                                                                       i = -1;
+                                                                                       break;
+                                                                               }
+                                                                       }
+
+                                                                       if (i < 0)
+                                                                               continue;
+
+                                                                       if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) {
+                                                                               if (pm.MemberType != ParsedParameters[parsed_param_count].TypeSpec) {
+                                                                                       parameters_match = parsed_param_count + 1;
+                                                                                       continue;
+                                                                               }
+                                                                       } else {
+                                                                               if (parsed_param_count != pm.Parameters.Count)
+                                                                                       continue;
+                                                                       }
+                                                               }
+
+                                                               if (member != null) {
+                                                                       Report.Warning (419, 3, mc.Location,
+                                                                               "Ambiguous reference in cref attribute `{0}'. Assuming `{1}' but other overloads including `{2}' have also matched",
+                                                                               cref, member.GetSignatureForError (), m.GetSignatureForError ());
+
+                                                                       break;
+                                                               }
+
+                                                               member = m;
+                                                       }
+                                               }
 
-                       Report.Warning (1574, 1, mc.Location, "XML comment on `{0}' has cref attribute `{1}' that could not be resolved",
-                               mc.GetSignatureForError (), cref);
+                                               // Continue with parent type for nested types
+                                               if (member == null) {
+                                                       type = type.DeclaringType;
+                                               } else {
+                                                       type = null;
+                                               }
+                                       } while (type != null);
 
-                       xref.SetAttribute ("cref", "!:" + name);
-               }
+                                       if (member == null && parameters_match >= 0) {
+                                               for (int i = parameters_match; i < parsed_param_count; ++i) {
+                                                       Report.Warning (1580, 1, mc.Location, "Invalid type for parameter `{0}' in XML comment cref attribute `{1}'",
+                                                                       (i + 1).ToString (), cref);
+                                               }
 
-               static string GetParametersFormatted (MemberInfo mi)
-               {
-                       MethodBase mb = mi as MethodBase;
-                       bool isSetter = false;
-                       PropertyInfo pi = mi as PropertyInfo;
-                       if (pi != null) {
-                               mb = pi.GetGetMethod ();
-                               if (mb == null) {
-                                       isSetter = true;
-                                       mb = pi.GetSetMethod ();
+                                               if (parameters_match == parsed_param_count + 1) {
+                                                       Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute `{0}'", cref);
+                                               }
+                                       }
                                }
                        }
-                       if (mb == null)
-                               return String.Empty;
-
-                       ParameterData parameters = TypeManager.GetParameterData (mb);
-                       if (parameters == null || parameters.Count == 0)
-                               return String.Empty;
-
-                       StringBuilder sb = new StringBuilder ();
-                       sb.Append ('(');
-                       for (int i = 0; i < parameters.Count; i++) {
-                               if (isSetter && i + 1 == parameters.Count)
-                                       break; // skip "value".
-                               if (i > 0)
-                                       sb.Append (',');
-                               Type t = parameters.ParameterType (i);
-                               sb.Append (GetSignatureForDoc (t));
-                       }
-                       sb.Append (')');
-                       return sb.ToString ();
-               }
 
-               static string GetBodyIdentifierFromName (string name)
-               {
-                       string identifier = name;
-
-                       if (name.Length > 0 && name [name.Length - 1] == ']') {
-                               string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
-                               int last = tmp.LastIndexOf ('[');
-                               if (last > 0)
-                                       identifier = tmp.Substring (0, last).Trim (wsChars);
+                       if (member == null) {
+                               Report.Warning (1574, 1, mc.Location, "XML comment on `{0}' has cref attribute `{1}' that could not be resolved",
+                                       mc.GetSignatureForError (), cref);
+                               cref = "!:" + cref;
+                       } else if (member == InternalType.Namespace) {
+                               cref = "N:" + fne.GetSignatureForError ();
+                       } else {
+                               prefix = GetMemberDocHead (member);
+                               cref = prefix + member.GetSignatureForDocumentation ();
                        }
 
-                       return identifier;
-               }
-
-               static void Report419 (MemberCore mc, string memberName, MemberInfo [] mis)
-               {
-                       Report.Warning (419, 3, mc.Location, 
-                               "Ambiguous reference in cref attribute `{0}'. Assuming `{1}' but other overloads including `{2}' have also matched",
-                               memberName,
-                               TypeManager.GetFullNameSignature (mis [0]),
-                               TypeManager.GetFullNameSignature (mis [1]));
+                       xref.SetAttribute ("cref", cref);
                }
 
                //
                // Get a prefix from member type for XML documentation (used
                // to formalize cref target name).
                //
-               static string GetMemberDocHead (MemberTypes type)
+               static string GetMemberDocHead (MemberSpec type)
                {
-                       switch (type) {
-                       case MemberTypes.Constructor:
-                       case MemberTypes.Method:
+                       if (type is FieldSpec)
+                               return "F:";
+                       if (type is MethodSpec)
                                return "M:";
-                       case MemberTypes.Event:
+                       if (type is EventSpec)
                                return "E:";
-                       case MemberTypes.Field:
-                               return "F:";
-                       case MemberTypes.NestedType:
-                       case MemberTypes.TypeInfo:
-                               return "T:";
-                       case MemberTypes.Property:
+                       if (type is PropertySpec)
                                return "P:";
-                       }
-                       return "!:";
-               }
-
-               // MethodCore
-
-               //
-               // Returns a string that represents the signature for this 
-               // member which should be used in XML documentation.
-               //
-               public static string GetMethodDocCommentName (MemberCore mc, Parameters parameters, DeclSpace ds)
-               {
-                       Parameter [] plist = parameters.FixedParameters;
-                       string paramSpec = String.Empty;
-                       if (plist != null) {
-                               StringBuilder psb = new StringBuilder ();
-                               foreach (Parameter p in plist) {
-                                       psb.Append (psb.Length != 0 ? "," : "(");
-                                       psb.Append (GetSignatureForDoc (p.ExternalType ()));
-                               }
-                               paramSpec = psb.ToString ();
-                       }
+                       if (type is TypeSpec)
+                               return "T:";
 
-                       if (paramSpec.Length > 0)
-                               paramSpec += ")";
-
-                       string name = mc is Constructor ? "#ctor" : mc.Name;
-                       string suffix = String.Empty;
-                       Operator op = mc as Operator;
-                       if (op != null) {
-                               switch (op.OperatorType) {
-                               case Operator.OpType.Implicit:
-                               case Operator.OpType.Explicit:
-                                       suffix = "~" + GetSignatureForDoc (op.MethodBuilder.ReturnType);
-                                       break;
-                               }
-                       }
-                       return String.Concat (mc.DocCommentHeader, ds.Name, ".", name, paramSpec, suffix);
-               }
-
-               static string GetSignatureForDoc (Type type)
-               {
-                       return TypeManager.IsGenericParameter (type) ?
-                               "`" + TypeManager.GenericParameterPosition (type) :
-                               type.FullName.Replace ("+", ".").Replace ('&', '@');
+                       throw new NotImplementedException (type.GetType ().ToString ());
                }
 
                //
@@ -899,153 +537,106 @@ namespace Mono.CSharp {
                // FIXME: with a few effort, it could be done with XmlReader,
                // that means removal of DOM use.
                //
-               internal static void OnMethodGenerateDocComment (
-                       MethodCore mc, XmlElement el)
+               void CheckParametersComments (MemberCore member, IParametersMember paramMember, XmlElement el)
                {
-                       Hashtable paramTags = new Hashtable ();
+                       HashSet<string> found_tags = null;
                        foreach (XmlElement pelem in el.SelectNodes ("param")) {
-                               int i;
                                string xname = pelem.GetAttribute ("name");
                                if (xname.Length == 0)
                                        continue; // really? but MS looks doing so
-                               if (xname != "" && mc.Parameters.GetParameterByName (xname, out i) == null)
-                                       Report.Warning (1572, 2, mc.Location, "XML comment on `{0}' has a param tag for `{1}', but there is no parameter by that name",
-                                               mc.GetSignatureForError (), xname);
-                               else if (paramTags [xname] != null)
-                                       Report.Warning (1571, 2, mc.Location, "XML comment on `{0}' has a duplicate param tag for `{1}'",
-                                               mc.GetSignatureForError (), xname);
-                               paramTags [xname] = xname;
-                       }
-                       Parameter [] plist = mc.Parameters.FixedParameters;
-                       foreach (Parameter p in plist) {
-                               if (paramTags.Count > 0 && paramTags [p.Name] == null)
-                                       Report.Warning (1573, 4, mc.Location, "Parameter `{0}' has no matching param tag in the XML comment for `{1}'",
-                                               p.Name, mc.GetSignatureForError ());
-                       }
-               }
-
-               private static void Normalize (MemberCore mc, ref string name)
-               {
-                       if (name.Length > 0 && name [0] == '@')
-                               name = name.Substring (1);
-                       else if (name == "this")
-                               name = "Item";
-                       else if (Tokenizer.IsKeyword (name) && !IsTypeName (name))
-                               Report.Warning (1041, 1, mc.Location, "Identifier expected. `{0}' is a keyword", name);
-               }
-
-               private static bool IsTypeName (string name)
-               {
-                       switch (name) {
-                       case "bool":
-                       case "byte":
-                       case "char":
-                       case "decimal":
-                       case "double":
-                       case "float":
-                       case "int":
-                       case "long":
-                       case "object":
-                       case "sbyte":
-                       case "short":
-                       case "string":
-                       case "uint":
-                       case "ulong":
-                       case "ushort":
-                       case "void":
-                               return true;
-                       }
-                       return false;
-               }
-       }
 
-       //
-       // Implements XML documentation generation.
-       //
-       public class Documentation
-       {
-               public Documentation (string xml_output_filename)
-               {
-                       docfilename = xml_output_filename;
-                       XmlDocumentation = new XmlDocument ();
-                       XmlDocumentation.PreserveWhitespace = false;
-               }
+                               if (found_tags == null) {
+                                       found_tags = new HashSet<string> ();
+                               }
 
-               private string docfilename;
+                               if (xname != "" && paramMember.Parameters.GetParameterIndexByName (xname) < 0) {
+                                       Report.Warning (1572, 2, member.Location,
+                                               "XML comment on `{0}' has a param tag for `{1}', but there is no parameter by that name",
+                                               member.GetSignatureForError (), xname);
+                                       continue;
+                               }
 
-               //
-               // Used to create element which helps well-formedness checking.
-               //
-               public XmlDocument XmlDocumentation;
+                               if (found_tags.Contains (xname)) {
+                                       Report.Warning (1571, 2, member.Location,
+                                               "XML comment on `{0}' has a duplicate param tag for `{1}'",
+                                               member.GetSignatureForError (), xname);
+                                       continue;
+                               }
 
-               //
-               // The output for XML documentation.
-               //
-               public XmlWriter XmlCommentOutput;
+                               found_tags.Add (xname);
+                       }
 
-               //
-               // Stores XmlDocuments that are included in XML documentation.
-               // Keys are included filenames, values are XmlDocuments.
-               //
-               public Hashtable StoredDocuments = new Hashtable ();
+                       if (found_tags != null) {
+                               foreach (Parameter p in paramMember.Parameters.FixedParameters) {
+                                       if (!found_tags.Contains (p.Name) && !(p is ArglistParameter))
+                                               Report.Warning (1573, 4, member.Location,
+                                                       "Parameter `{0}' has no matching param tag in the XML comment for `{1}'",
+                                                       p.Name, member.GetSignatureForError ());
+                               }
+                       }
+               }
 
                //
                // Outputs XML documentation comment from tokenized comments.
                //
-               public bool OutputDocComment (string asmfilename)
+               public bool OutputDocComment (string asmfilename, string xmlFileName)
                {
                        XmlTextWriter w = null;
                        try {
-                               w = new XmlTextWriter (docfilename, null);
+                               w = new XmlTextWriter (xmlFileName, null);
                                w.Indentation = 4;
                                w.Formatting = Formatting.Indented;
                                w.WriteStartDocument ();
                                w.WriteStartElement ("doc");
                                w.WriteStartElement ("assembly");
                                w.WriteStartElement ("name");
-                               w.WriteString (Path.ChangeExtension (asmfilename, null));
+                               w.WriteString (Path.GetFileNameWithoutExtension (asmfilename));
                                w.WriteEndElement (); // name
                                w.WriteEndElement (); // assembly
                                w.WriteStartElement ("members");
                                XmlCommentOutput = w;
-                               GenerateDocComment ();
+                               module.GenerateDocComment (this);
                                w.WriteFullEndElement (); // members
                                w.WriteEndElement ();
                                w.WriteWhitespace (Environment.NewLine);
                                w.WriteEndDocument ();
                                return true;
                        } catch (Exception ex) {
-                               Report.Error (1569, "Error generating XML documentation file `{0}' (`{1}')", docfilename, ex.Message);
+                               Report.Error (1569, "Error generating XML documentation file `{0}' (`{1}')", xmlFileName, ex.Message);
                                return false;
                        } finally {
                                if (w != null)
                                        w.Close ();
                        }
                }
+       }
 
-               //
-               // Fixes full type name of each documented types/members up.
-               //
-               public void GenerateDocComment ()
-               {
-                       TypeContainer root = RootContext.ToplevelTypes;
-                       if (root.Interfaces != null)
-                               foreach (Interface i in root.Interfaces) 
-                                       DocUtil.GenerateTypeDocComment (i, null);
+       class DocumentationParameter
+       {
+               public readonly Parameter.Modifier Modifier;
+               public FullNamedExpression Type;
+               TypeSpec type;
 
-                       if (root.Types != null)
-                               foreach (TypeContainer tc in root.Types)
-                                       DocUtil.GenerateTypeDocComment (tc, null);
+               public DocumentationParameter (Parameter.Modifier modifier, FullNamedExpression type)
+                       : this (type)
+               {
+                       this.Modifier = modifier;
+               }
 
-                       if (root.Delegates != null)
-                               foreach (Delegate d in root.Delegates) 
-                                       DocUtil.GenerateDocComment (d, null);
+               public DocumentationParameter (FullNamedExpression type)
+               {
+                       this.Type = type;
+               }
 
-                       if (root.Enums != null)
-                               foreach (Enum e in root.Enums)
-                                       e.GenerateDocComment (null);
+               public TypeSpec TypeSpec {
+                       get {
+                               return type;
+                       }
+               }
 
+               public void Resolve (IMemberContext context)
+               {
+                       type = Type.ResolveAsType (context);
                }
        }
 }
-#endif