2005-12-23 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / mcs / doc.cs
index 66c004c02dc068f7b4051695fb4899ba15827820..8f0d14fbce42aa7dc0b6a3a2be63be8d826aacae 100644 (file)
@@ -333,8 +333,7 @@ namespace Mono.CSharp {
                        // no need to detect warning 419 here
                        return FindDocumentedMember (mc, parent,
                                identifier.Substring (index + 1),
-                               Type.EmptyTypes,
-                               ds, out warn, cref, false, null) as Type;
+                               null, ds, out warn, cref, false, null).Member as Type;
                }
 
                private static MemberInfo [] empty_member_infos =
@@ -355,37 +354,56 @@ namespace Mono.CSharp {
                        return FilterOverridenMembersOut (type, (MemberInfo []) ml);
                }
 
+               static bool IsOverride (PropertyInfo deriv_prop, PropertyInfo base_prop)
+               {
+                       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;
+               }
+
                private static MemberInfo [] FilterOverridenMembersOut (
                        Type type, MemberInfo [] ml)
                {
                        if (ml == null)
                                return empty_member_infos;
-                       if (type.IsInterface)
-                               return ml;
 
                        ArrayList al = new ArrayList (ml.Length);
                        for (int i = 0; i < ml.Length; i++) {
-                               // Interface methods which are returned
-                               // from the filter must exist in the 
-                               // target type (if there is only a 
-                               // private implementation, then the 
-                               // filter should not return it.)
-                               // This filtering is required to 
-                               // deambiguate results.
-                               //
-                               // It is common to properties, so check it here.
-                               if (ml [i].DeclaringType.IsInterface)
-                                       continue;
-
-                               MethodBase x = ml [i] as MethodBase;
-                               if (x != null) {
+                               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 y = ml [j] as MethodBase;
-                                               if (y != null &&
-                                                       Invocation.IsOverride (y, x)) {
+                                               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;
                                                }
@@ -398,28 +416,59 @@ namespace Mono.CSharp {
                        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;
+
+                       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 MemberInfo FindDocumentedMember (MemberCore mc,
+               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;
-                       MethodSignature msig = new MethodSignature (memberName, null, paramList);
-                       MemberInfo [] mis = FindMethodBase (type, 
-                               BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
-                               msig);
+                       return FoundMember.Empty;
+               }
 
-                       if (warn419 && mis.Length > 0) {
-                               if (IsAmbiguous (mis))
-                                       Report419 (mc, nameForError, mis);
-                               return mis [0];
-                       }
+               private static MemberInfo FindDocumentedMemberNoNest (
+                       MemberCore mc, Type type, string memberName,
+                       Type [] paramList, DeclSpace ds, out int warningType, 
+                       string cref, bool warn419, string nameForError)
+               {
+                       warningType = 0;
+                       MemberInfo [] mis;
 
-                       if (paramList.Length == 0) {
+                       if (paramList == null) {
                                // search for fields/events etc.
                                mis = TypeManager.MemberLookup (type, null,
                                        type, MemberTypes.All,
@@ -433,6 +482,17 @@ namespace Mono.CSharp {
                                return mis [0];
                        }
 
+                       MethodSignature msig = new MethodSignature (memberName, null, paramList);
+                       mis = FindMethodBase (type, 
+                               BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
+                               msig);
+
+                       if (warn419 && mis.Length > 0) {
+                               if (IsAmbiguous (mis))
+                                       Report419 (mc, nameForError, mis);
+                               return mis [0];
+                       }
+
                        // search for operators (whose parameters exactly
                        // matches with the list) and possibly report CS1581.
                        string oper = null;
@@ -588,7 +648,7 @@ namespace Mono.CSharp {
                        }
                        else {
                                name = signature;
-                               parameters = String.Empty;
+                               parameters = null;
                        }
                        Normalize (mc, ref name);
 
@@ -612,8 +672,12 @@ namespace Mono.CSharp {
                        }
 
                        // check if parameters are valid
-                       Type [] parameterTypes = Type.EmptyTypes;
-                       if (parameters.Length > 0) {
+                       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++) {
@@ -634,19 +698,13 @@ namespace Mono.CSharp {
                        if (type != null
                                // delegate must not be referenced with args
                                && (!type.IsSubclassOf (typeof (System.Delegate))
-                               || parameterTypes.Length == 0)) {
+                               || parameterTypes == null)) {
                                string result = type.FullName.Replace ("+", ".")
                                        + (bracePos < 0 ? String.Empty : signature.Substring (bracePos));
                                xref.SetAttribute ("cref", "T:" + result);
                                return; // a type
                        }
 
-                       // don't use identifier here. System[] is not alloed.
-                       if (RootNamespace.Global.IsNamespace (name)) {
-                               xref.SetAttribute ("cref", "N:" + name);
-                               return; // a namespace
-                       }
-
                        int period = name.LastIndexOf ('.');
                        if (period > 0) {
                                string typeName = name.Substring (0, period);
@@ -655,26 +713,47 @@ namespace Mono.CSharp {
                                type = FindDocumentedType (mc, typeName, ds, cref);
                                int warnResult;
                                if (type != null) {
-                                       MemberInfo mi = FindDocumentedMember (mc, type, memberName, parameterTypes, ds, out warnResult, cref, true, name);
+                                       FoundMember fm = FindDocumentedMember (mc, type, memberName, parameterTypes, ds, out warnResult, cref, true, name);
                                        if (warnResult > 0)
                                                return;
-                                       if (mi != null) {
-                                               xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + type.FullName.Replace ("+", ".") + "." + memberName + GetParametersFormatted (mi));
+                                       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) + fm.Type.FullName.Replace ("+", ".") + "." + memberName + GetParametersFormatted (mi));
                                                return; // a member of a type
                                        }
                                }
                        }
                        else {
                                int warnResult;
-                               MemberInfo mi = FindDocumentedMember (mc, ds.TypeBuilder, name, parameterTypes, ds, out warnResult, cref, true, name);
+                               FoundMember fm = FindDocumentedMember (mc, ds.TypeBuilder, name, parameterTypes, ds, out warnResult, cref, true, name);
                                if (warnResult > 0)
                                        return;
-                               if (mi != null) {
-                                       xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + ds.TypeBuilder.FullName.Replace ("+", ".") + "." + name + GetParametersFormatted (mi));
+                               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) + fm.Type.FullName.Replace ("+", ".") + "." + 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
+                       }
+
                        Report.Warning (1574, 1, mc.Location, "XML comment on `{0}' has cref attribute `{1}' that could not be resolved",
                                mc.GetSignatureForError (), cref);
 
@@ -769,7 +848,6 @@ namespace Mono.CSharp {
                public static string GetMethodDocCommentName (MethodCore mc, DeclSpace ds)
                {
                        Parameter [] plist = mc.Parameters.FixedParameters;
-                       Parameter parr = mc.Parameters.ArrayParameter;
                        string paramSpec = String.Empty;
                        if (plist != null) {
                                StringBuilder psb = new StringBuilder ();
@@ -779,10 +857,6 @@ namespace Mono.CSharp {
                                }
                                paramSpec = psb.ToString ();
                        }
-                       if (parr != null)
-                               paramSpec += String.Concat (
-                                       paramSpec == String.Empty ? "(" : ",",
-                                       parr.ParameterType.FullName.Replace ("+", "."));
 
                        if (paramSpec.Length > 0)
                                paramSpec += ")";
@@ -826,12 +900,10 @@ namespace Mono.CSharp {
                                paramTags [xname] = xname;
                        }
                        Parameter [] plist = mc.Parameters.FixedParameters;
-                       if (plist != null) {
-                               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 ());
-                               }
+                       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 ());
                        }
                }