Emit correct sequence info for iterators
[mono.git] / mcs / mcs / doc.cs
index 908e3c6cede31483b7ac878b016abaaf2767738d..19340bf6c1e3c6241c6e05ef14d2efc8a46208df 100644 (file)
@@ -8,6 +8,7 @@
 // Dual licensed under the terms of the MIT X11 or GNU GPL
 //
 // Copyright 2004 Novell, Inc.
+// Copyright 2011 Xamarin Inc
 //
 //
 
@@ -31,11 +32,12 @@ namespace Mono.CSharp
                readonly XmlDocument XmlDocumentation;
 
                readonly ModuleContainer module;
+               readonly ModuleContainer doc_module;
 
                //
                // The output for XML documentation.
                //
-               public XmlWriter XmlCommentOutput;
+               XmlWriter XmlCommentOutput;
 
                static readonly string line_head = Environment.NewLine + "            ";
 
@@ -47,6 +49,9 @@ namespace Mono.CSharp
 
                public DocumentationBuilder (ModuleContainer module)
                {
+                       doc_module = new ModuleContainer (module.Compiler);
+                       doc_module.DocumentationBuilder = this;
+
                        this.module = module;
                        XmlDocumentation = new XmlDocument ();
                        XmlDocumentation.PreserveWhitespace = false;
@@ -122,7 +127,10 @@ namespace Mono.CSharp
 
                        XmlElement el = n as XmlElement;
                        if (el != null) {
-                               mc.OnGenerateDocComment (el);
+                               var pm = mc as IParametersMember;
+                               if (pm != null) {
+                                       CheckParametersComments (mc, pm, el);
+                               }
 
                                // FIXME: it could be done with XmlReader
                                XmlNodeList nl = n.SelectNodes (".//include");
@@ -137,7 +145,7 @@ namespace Mono.CSharp
                                }
 
                                // FIXME: it could be done with XmlReader
-                               DeclSpace ds_target = mc as DeclSpace;
+                               var ds_target = mc as TypeContainer;
                                if (ds_target == null)
                                        ds_target = mc.Parent;
 
@@ -147,6 +155,10 @@ namespace Mono.CSharp
                                        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);
@@ -205,7 +217,7 @@ namespace Mono.CSharp
                //
                // Handles <see> elements.
                //
-               void HandleSee (MemberCore mc, DeclSpace ds, XmlElement see)
+               void HandleSee (MemberCore mc, TypeContainer ds, XmlElement see)
                {
                        HandleXrefCommon (mc, ds, see);
                }
@@ -213,7 +225,7 @@ namespace Mono.CSharp
                //
                // Handles <seealso> elements.
                //
-               void HandleSeeAlso (MemberCore mc, DeclSpace ds, XmlElement seealso)
+               void HandleSeeAlso (MemberCore mc, TypeContainer ds, XmlElement seealso)
                {
                        HandleXrefCommon (mc, ds, seealso);
                }
@@ -221,20 +233,65 @@ namespace Mono.CSharp
                //
                // Handles <exception> elements.
                //
-               void HandleException (MemberCore mc, DeclSpace ds, XmlElement seealso)
+               void HandleException (MemberCore mc, TypeContainer ds, XmlElement seealso)
                {
                        HandleXrefCommon (mc, ds, seealso);
                }
 
+               //
+               // Handles <typeparam /> node
+               //
+               void HandleTypeParam (MemberCore mc, XmlElement node)
+               {
+                       if (!node.HasAttribute ("name"))
+                               return;
+
+                       string tp_name = node.GetAttribute ("name");
+                       if (mc.CurrentTypeParameters != null) {
+                               if (mc.CurrentTypeParameters.Find (tp_name) != null)
+                                       return;
+                       }
+                       
+                       // 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);
+               }
+
+               //
+               // Handles <typeparamref /> node
+               //
+               void HandleTypeParamRef (MemberCore mc, XmlElement node)
+               {
+                       if (!node.HasAttribute ("name"))
+                               return;
+
+                       string tp_name = node.GetAttribute ("name");
+                       var member = mc;
+                       do {
+                               if (member.CurrentTypeParameters != null) {
+                                       if (member.CurrentTypeParameters.Find (tp_name) != null)
+                                               return;
+                               }
+
+                               member = member.Parent;
+                       } while (member != null);
+
+                       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);
+               }
+
                FullNamedExpression ResolveMemberName (IMemberContext context, MemberName mn)
                {
                        if (mn.Left == null)
-                               return context.LookupNamespaceOrType (mn.Name, mn.Arity, Location.Null, /*ignore_cs0104=*/ false);
+                               return context.LookupNamespaceOrType (mn.Name, mn.Arity, LookupMode.Probing, Location.Null);
 
                        var left = ResolveMemberName (context, mn.Left);
                        var ns = left as Namespace;
                        if (ns != null)
-                               return ns.Lookup (context, mn.Name, mn.Arity, Location.Null);
+                               return ns.LookupTypeOrNamespace (context, mn.Name, mn.Arity, LookupMode.Probing, Location.Null);
 
                        TypeExpr texpr = left as TypeExpr;
                        if (texpr != null) {
@@ -251,7 +308,7 @@ namespace Mono.CSharp
                //
                // Processes "see" or "seealso" elements from cref attribute.
                //
-               void HandleXrefCommon (MemberCore mc, DeclSpace ds, XmlElement xref)
+               void HandleXrefCommon (MemberCore mc, TypeContainer ds, XmlElement xref)
                {
                        string cref = xref.GetAttribute ("cref");
                        // when, XmlReader, "if (cref == null)"
@@ -262,17 +319,17 @@ namespace Mono.CSharp
                        if (cref.Length > 2 && cref [1] == ':')
                                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 NamespaceEntry (doc_module, null, source_file, null);
+                       var source_file = new CompilationSourceFile (doc_module);
+                       var report = new Report (doc_module.Compiler, new NullReportPrinter ());
 
-                       Report parse_report = new Report (new NullReportPrinter ());
-                       var parser = new CSharpParser (seekable, source_file, parse_report);
+                       var parser = new CSharpParser (seekable, source_file, report);
                        ParsedParameters = null;
                        ParsedName = null;
                        ParsedBuiltinType = null;
@@ -280,7 +337,7 @@ namespace Mono.CSharp
                        parser.Lexer.putback_char = Tokenizer.DocumentationXref;
                        parser.Lexer.parsing_generic_declaration_doc = true;
                        parser.parse ();
-                       if (parse_report.Errors > 0) {
+                       if (report.Errors > 0) {
                                Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'",
                                        mc.GetSignatureForError (), cref);
 
@@ -296,7 +353,7 @@ namespace Mono.CSharp
                        // Try built-in type first because we are using ParsedName as identifier of
                        // member names on built-in types
                        //
-                       if (ParsedBuiltinType != null && ParsedParameters == null) {
+                       if (ParsedBuiltinType != null && (ParsedParameters == null || ParsedName != null)) {
                                member = ParsedBuiltinType.Type;
                        } else {
                                member = null;
@@ -314,7 +371,7 @@ namespace Mono.CSharp
                                                if (fne != null) {
                                                        var ns = fne as Namespace;
                                                        if (ns != null) {
-                                                               fne = ns.Lookup (mc, ParsedName.Name, ParsedName.Arity, Location.Null);
+                                                               fne = ns.LookupTypeOrNamespace (mc, ParsedName.Name, ParsedName.Arity, LookupMode.Probing, Location.Null);
                                                                if (fne != null) {
                                                                        member = fne.Type;
                                                                }
@@ -339,9 +396,11 @@ namespace Mono.CSharp
                                }
 
                                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);
                                }
 
                                if (type != null) {
@@ -452,15 +511,6 @@ namespace Mono.CSharp
                        xref.SetAttribute ("cref", cref);
                }
 
-               void Report419 (MemberCore mc, string member_name, MemberSpec [] mis)
-               {
-                       Report.Warning (419, 3, mc.Location, 
-                               "Ambiguous reference in cref attribute `{0}'. Assuming `{1}' but other overloads including `{2}' have also matched",
-                               member_name,
-                               TypeManager.GetFullNameSignature (mis [0]),
-                               TypeManager.GetFullNameSignature (mis [1]));
-               }
-
                //
                // Get a prefix from member type for XML documentation (used
                // to formalize cref target name).
@@ -488,27 +538,42 @@ 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, Report Report)
+               void CheckParametersComments (MemberCore member, IParametersMember paramMember, XmlElement el)
                {
-                       var paramTags = new Dictionary<string, string> ();
+                       HashSet<string> found_tags = null;
                        foreach (XmlElement pelem in el.SelectNodes ("param")) {
                                string xname = pelem.GetAttribute ("name");
                                if (xname.Length == 0)
                                        continue; // really? but MS looks doing so
-                               if (xname != "" && mc.ParameterInfo.GetParameterIndexByName (xname) < 0)
-                                       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.ContainsKey (xname))
-                                       Report.Warning (1571, 2, mc.Location, "XML comment on `{0}' has a duplicate param tag for `{1}'",
-                                               mc.GetSignatureForError (), xname);
-                               paramTags [xname] = xname;
+
+                               if (found_tags == null) {
+                                       found_tags = new HashSet<string> ();
+                               }
+
+                               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;
+                               }
+
+                               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;
+                               }
+
+                               found_tags.Add (xname);
                        }
-                       IParameterData [] plist = mc.ParameterInfo.FixedParameters;
-                       foreach (Parameter p in plist) {
-                               if (paramTags.Count > 0 && !paramTags.ContainsKey (p.Name))
-                                       Report.Warning (1573, 4, mc.Location, "Parameter `{0}' has no matching param tag in the XML comment for `{1}'",
-                                               p.Name, mc.GetSignatureForError ());
+
+                       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 ());
+                               }
                        }
                }
 
@@ -551,6 +616,7 @@ namespace Mono.CSharp
        {
                public readonly Parameter.Modifier Modifier;
                public FullNamedExpression Type;
+               TypeSpec type;
 
                public DocumentationParameter (Parameter.Modifier modifier, FullNamedExpression type)
                        : this (type)
@@ -565,13 +631,13 @@ namespace Mono.CSharp
 
                public TypeSpec TypeSpec {
                        get {
-                               return Type == null ? null : Type.Type;
+                               return type;
                        }
                }
 
                public void Resolve (IMemberContext context)
                {
-                       Type = Type.ResolveAsTypeTerminal (context, true);
+                       type = Type.ResolveAsType (context);
                }
        }
 }