X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Ftools%2Fmdoc%2FMono.Documentation%2Fmonodocer.cs;h=8b5b5ab08e4d440f58d3dd88d1b732cbd5ccc449;hb=d80283d1e82e9b954e0b7c3494d8a859aea11478;hp=0a031767cce7e042b9df3374caacd271d33391f8;hpb=ccdf8c3274d1793ffeddedfd784d49707feea62a;p=mono.git diff --git a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs index 0a031767cce..8b5b5ab08e4 100644 --- a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs +++ b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs @@ -133,7 +133,9 @@ class MDocUpdater : MDocCommand List assemblies; readonly DefaultAssemblyResolver assemblyResolver = new DefaultAssemblyResolver(); - bool multiassembly; + string apistyle = string.Empty; + bool isClassicRun; + bool delete; bool show_exceptions; bool no_assembly_versions, ignore_missing_types; @@ -192,7 +194,14 @@ class MDocUpdater : MDocCommand { return !string.IsNullOrWhiteSpace (droppedNamespace); } - + + /// Logic flag to signify that we should list assemblies at the method level, since there are multiple + /// assemblies for a given type/method. + public bool IsMultiAssembly { + get { + return apistyle == "classic" || apistyle == "unified"; + } + } static List droppedAssemblies = new List(); @@ -279,9 +288,9 @@ class MDocUpdater : MDocCommand { "preserve", "Do not delete members that don't exist in the assembly, but rather mark them as preserved.", v => PreserveTag = "true" }, - { "multiassembly", - "Allow types to be in multiple assemblies.", - v => multiassembly = true }, + { "api-style=", + "Denotes the apistyle. Currently, only `classic` and `unified` are supported. `classic` set of assemblies should be run first, immediately followed by 'unified' assemblies with the `dropns` parameter.", + v => { apistyle = v.ToLowerInvariant (); }}, }; var assemblies = Parse (p, args, "update", "[OPTIONS]+ ASSEMBLIES", @@ -290,7 +299,17 @@ class MDocUpdater : MDocCommand return; if (assemblies.Count == 0) Error ("No assemblies specified."); - + + // validation for the api-style parameter + if (apistyle == "classic") + isClassicRun = true; + else if (apistyle == "unified") { + if (!droppedAssemblies.Any ()) + Error ("api-style 'unified' must also supply the 'dropns' parameter with at least one assembly and dropped namespace."); + } else if (!string.IsNullOrWhiteSpace (apistyle)) + Error ("api-style '{0}' is not currently supported", apistyle); + + foreach (var dir in assemblies .Where (a => a.Contains (Path.DirectorySeparatorChar)) .Select (a => Path.GetDirectoryName (a))) @@ -772,7 +791,7 @@ class MDocUpdater : MDocCommand private void AddIndexAssembly (AssemblyDefinition assembly, XmlElement parent) { XmlElement index_assembly = null; - if (multiassembly) + if (IsMultiAssembly) index_assembly = (XmlElement)parent.SelectSingleNode ("Assembly[@Name='"+ assembly.Name.Name +"']"); if (index_assembly == null) @@ -852,7 +871,7 @@ class MDocUpdater : MDocCommand XmlElement index_types = WriteElement(index.DocumentElement, "Types"); XmlElement index_assemblies = WriteElement(index.DocumentElement, "Assemblies"); - if (!multiassembly) + if (!IsMultiAssembly) index_assemblies.RemoveAll (); @@ -1045,7 +1064,7 @@ class MDocUpdater : MDocCommand saveDoc (); var unifiedAssemblyNode = doc.SelectSingleNode ("/Type/AssemblyInfo[@apistyle='unified']"); - var classicAssemblyNode = doc.SelectSingleNode ("/Type/AssemblyInfo[@apistyle='classic']"); + var classicAssemblyNode = doc.SelectSingleNode ("/Type/AssemblyInfo[not(@apistyle) or @apistyle='classic']"); var unifiedMembers = doc.SelectNodes ("//Member[@apistyle='unified']|//Member/AssemblyInfo[@apistyle='unified']"); var classicMembers = doc.SelectNodes ("//Member[@apistyle='classic']|//Member/AssemblyInfo[@apistyle='classic']"); bool isUnifiedRun = HasDroppedAnyNamespace (); @@ -1265,10 +1284,10 @@ class MDocUpdater : MDocCommand XmlElement mm = MakeMember(basefile, new DocsNodeInfo (null, m)); if (mm == null) continue; - if (MDocUpdater.SwitchingToMagicTypes) { + if (MDocUpdater.SwitchingToMagicTypes || MDocUpdater.HasDroppedNamespace (m)) { // this is a unified style API that obviously doesn't exist in the classic API. Let's mark // it with apistyle="unified", so that it's not displayed for classic style APIs - mm.SetAttribute ("apistyle", "unified"); + mm.AddApiStyle (ApiStyle.Unified); } members.AppendChild( mm ); @@ -1379,7 +1398,7 @@ class MDocUpdater : MDocCommand bool unifiedRun = HasDroppedNamespace (type); - var classicAssemblyInfo = member.SelectSingleNode ("AssemblyInfo[@apistyle='classic']"); + var classicAssemblyInfo = member.SelectSingleNode ("AssemblyInfo[not(@apistyle) or @apistyle='classic']"); bool nodeIsClassic = classicAssemblyInfo != null || member.HasApiStyle (ApiStyle.Classic); var unifiedAssemblyInfo = member.SelectSingleNode ("AssemblyInfo[@apistyle='unified']"); bool nodeIsUnified = unifiedAssemblyInfo != null || member.HasApiStyle (ApiStyle.Unified); @@ -1398,12 +1417,13 @@ class MDocUpdater : MDocCommand } else if (unifiedRun && nodeIsClassic) { // this is a unified run, and the member doesn't exist, but is marked as being in the classic assembly. member.RemoveApiStyle (ApiStyle.Unified); + member.AddApiStyle (ApiStyle.Classic); Warning ("Not removing '{0}' since it's still in the classic assembly.", signature); } else if (unifiedRun && !nodeIsClassic) { // unified run, and the node is not classic, which means it doesn't exist anywhere. actuallyDelete (); } else { - if (!nodeIsClassic && !nodeIsUnified) { // regular codepath (ie. not classic/unified) + if (!isClassicRun || (isClassicRun && !nodeIsClassic && !nodeIsUnified)) { // regular codepath (ie. not classic/unified) actuallyDelete (); } else { // this is a classic run Warning ("Removing classic from '{0}' ... will be removed in the unified run if not present there.", signature); @@ -1659,18 +1679,25 @@ class MDocUpdater : MDocCommand /// Adds an AssemblyInfo with AssemblyName node to an XmlElement. /// The assembly that was either added, or was already present - static XmlElement AddAssemblyNameToNode (XmlElement root, TypeDefinition type) + XmlElement AddAssemblyNameToNode (XmlElement root, TypeDefinition type) { return AddAssemblyNameToNode (root, type.Module); } /// Adds an AssemblyInfo with AssemblyName node to an XmlElement. /// The assembly that was either added, or was already present - static XmlElement AddAssemblyNameToNode (XmlElement root, ModuleDefinition module) + XmlElement AddAssemblyNameToNode (XmlElement root, ModuleDefinition module) { Func assemblyFilter = x => { var existingName = x.SelectSingleNode ("AssemblyName"); - return existingName != null && existingName.InnerText == module.Assembly.Name.Name; + + bool apiStyleMatches = true; + string currentApiStyle = x.GetAttribute ("apistyle"); + if ((HasDroppedNamespace (module) && !string.IsNullOrWhiteSpace (currentApiStyle) && currentApiStyle != "unified") || + (isClassicRun && (string.IsNullOrWhiteSpace (currentApiStyle) || currentApiStyle != "classic"))) { + apiStyleMatches = false; + } + return apiStyleMatches && (existingName == null || (existingName != null && existingName.InnerText == module.Assembly.Name.Name)); }; return AddAssemblyXmlNode ( @@ -1678,8 +1705,11 @@ class MDocUpdater : MDocCommand assemblyFilter, x => WriteElementText (x, "AssemblyName", module.Assembly.Name.Name), () => { XmlElement ass = WriteElement (root, "AssemblyInfo", forceNewElement: true); + if (MDocUpdater.HasDroppedNamespace (module)) - ass.SetAttribute ("apistyle", "unified"); + ass.AddApiStyle (ApiStyle.Unified); + if (isClassicRun) + ass.AddApiStyle (ApiStyle.Classic); return ass; }, module); } @@ -1739,7 +1769,7 @@ class MDocUpdater : MDocCommand WriteElementText(me, "MemberType", GetMemberType(mi)); if (!no_assembly_versions) { - if (!multiassembly) + if (!IsMultiAssembly) UpdateAssemblyVersions (me, mi, true); else { var node = AddAssemblyNameToNode (me, mi.Module); @@ -1785,8 +1815,8 @@ class MDocUpdater : MDocCommand XmlElement thisAssemblyNode = relevant.FirstOrDefault (valueMatches); if (thisAssemblyNode == null) { thisAssemblyNode = makeNewNode (); - setValue (thisAssemblyNode); } + setValue (thisAssemblyNode); if (isUnified) { thisAssemblyNode.AddApiStyle (ApiStyle.Unified); @@ -1987,7 +2017,10 @@ class MDocUpdater : MDocCommand member.AppendChild (link); AddTargets (em, info); - extensionMethods.Add (em); + var sig = em.SelectSingleNode ("Member/MemberSignature[@Language='C#']/@Value"); + if (!IsMultiAssembly || (IsMultiAssembly && sig != null && !extensionMethods.Any (ex => ex.SelectSingleNode ("Member/MemberSignature[@Language='C#']/@Value").Value == sig.Value))) { + extensionMethods.Add (em); + } } private static void RemoveExcept (XmlNode node, string[] except) @@ -2041,7 +2074,7 @@ class MDocUpdater : MDocCommand if (val == null) value = "null"; else if (val is Enum) value = val.ToString(); else if (val is IFormattable) { - value = ((IFormattable)val).ToString(); + value = ((IFormattable)val).ToString(null, CultureInfo.InvariantCulture); if (val is string) value = "\"" + value + "\""; } @@ -2357,7 +2390,7 @@ class MDocUpdater : MDocCommand n.ParentNode.RemoveChild(n); } - private static bool UpdateAssemblyVersions (XmlElement root, MemberReference member, bool add) + private bool UpdateAssemblyVersions (XmlElement root, MemberReference member, bool add) { TypeDefinition type = member as TypeDefinition; if (type == null) @@ -2376,8 +2409,11 @@ class MDocUpdater : MDocCommand return assembly.Name.Version.ToString(); } - private static bool UpdateAssemblyVersions(XmlElement root, AssemblyDefinition assembly, string[] assemblyVersions, bool add) + private bool UpdateAssemblyVersions(XmlElement root, AssemblyDefinition assembly, string[] assemblyVersions, bool add) { + if (IsMultiAssembly) + return false; + XmlElement av = (XmlElement) root.SelectSingleNode ("AssemblyVersions"); if (av != null) { // AssemblyVersions is not part of the spec @@ -2394,7 +2430,7 @@ class MDocUpdater : MDocCommand e = root.OwnerDocument.CreateElement("AssemblyInfo"); if (MDocUpdater.HasDroppedNamespace (assembly)) { - e.SetAttribute ("apistyle", "unified"); + e.AddApiStyle (ApiStyle.Unified); } root.AppendChild(e); @@ -2403,8 +2439,8 @@ class MDocUpdater : MDocCommand var thatNode = (XmlElement) root.SelectSingleNode (thatNodeFilter); if (MDocUpdater.HasDroppedNamespace (assembly) && thatNode != null) { // there's a classic node, we should add apistyles - e.SetAttribute ("apistyle", "unified"); - thatNode.SetAttribute ("apistyle", "classic"); + e.AddApiStyle (ApiStyle.Unified); + thatNode.AddApiStyle (ApiStyle.Classic); } return UpdateAssemblyVersionForAssemblyInfo (e, root, assemblyVersions, add); @@ -2971,26 +3007,6 @@ static class CecilExtensions { return method.GenericParameters.Count > 0; } - public static MemberReference Resolve (this MemberReference member) - { - FieldReference fr = member as FieldReference; - if (fr != null) - return fr.Resolve (); - MethodReference mr = member as MethodReference; - if (mr != null) - return mr.Resolve (); - TypeReference tr = member as TypeReference; - if (tr != null) - return tr.Resolve (); - PropertyReference pr = member as PropertyReference; - if (pr != null) - return pr; - EventReference er = member as EventReference; - if (er != null) - return er; - throw new NotSupportedException ("Cannot find definition for " + member.ToString ()); - } - public static TypeReference GetUnderlyingType (this TypeDefinition type) { if (!type.IsEnum) @@ -3042,6 +3058,39 @@ static class DocUtils { if (string.IsNullOrWhiteSpace (existingValue) || existingValue != styleString) { element.SetAttribute ("apistyle", styleString); } + + // Propagate the API style up to the membernode if necessary + if (element.LocalName == "AssemblyInfo" && element.ParentNode != null && element.ParentNode.LocalName == "Member") { + var member = element.ParentNode; + var unifiedAssemblyNode = member.SelectSingleNode ("AssemblyInfo[@apistyle='unified']"); + var classicAssemblyNode = member.SelectSingleNode ("AssemblyInfo[not(@apistyle) or @apistyle='classic']"); + + var parentAttribute = element.ParentNode.Attributes ["apistyle"]; + Action removeStyle = () => element.ParentNode.Attributes.Remove (parentAttribute); + Action propagateStyle = () => { + if (parentAttribute == null) { + // if it doesn't have the attribute, then add it + parentAttribute = element.OwnerDocument.CreateAttribute ("apistyle"); + parentAttribute.Value = styleString; + element.ParentNode.Attributes.Append (parentAttribute); + } + }; + + if ((style == ApiStyle.Classic && unifiedAssemblyNode != null) || (style == ApiStyle.Unified && classicAssemblyNode != null)) + removeStyle (); + else + propagateStyle (); + } + } + public static void AddApiStyle (this XmlNode node, ApiStyle style) + { + string styleString = style.ToString ().ToLowerInvariant (); + var existingAttribute = node.Attributes ["apistyle"]; + if (existingAttribute == null) { + existingAttribute = node.OwnerDocument.CreateAttribute ("apistyle"); + node.Attributes.Append (existingAttribute); + } + existingAttribute.Value = styleString; } public static void RemoveApiStyle (this XmlElement element, ApiStyle style) { @@ -3187,7 +3236,8 @@ static class DocUtils { { HashSet inheritedInterfaces = GetInheritedInterfaces (type); List userInterfaces = new List (); - foreach (TypeReference iface in type.Interfaces) { + foreach (var ii in type.Interfaces) { + var iface = ii.InterfaceType; TypeReference lookup = iface.Resolve () ?? iface; if (!inheritedInterfaces.Contains (GetQualifiedTypeName (lookup))) userInterfaces.Add (iface); @@ -3206,9 +3256,9 @@ static class DocUtils { Action a = null; a = t => { if (t == null) return; - foreach (TypeReference r in t.Interfaces) { - inheritedInterfaces.Add (GetQualifiedTypeName (r)); - a (r.Resolve ()); + foreach (var r in t.Interfaces) { + inheritedInterfaces.Add (GetQualifiedTypeName (r.InterfaceType)); + a (r.InterfaceType.Resolve ()); } }; TypeReference baseRef = type.BaseType; @@ -3221,8 +3271,8 @@ static class DocUtils { else baseRef = null; } - foreach (TypeReference r in type.Interfaces) - a (r.Resolve ()); + foreach (var r in type.Interfaces) + a (r.InterfaceType.Resolve ()); return inheritedInterfaces; } } @@ -4297,8 +4347,13 @@ public abstract class MemberFormatter { { return e.Name; } + + public string GetDeclaration (MemberReference mreference) + { + return GetDeclaration (mreference.Resolve ()); + } - public virtual string GetDeclaration (MemberReference member) + string GetDeclaration (IMemberDefinition member) { if (member == null) throw new ArgumentNullException ("member"); @@ -4562,8 +4617,8 @@ class ILFullMemberFormatter : MemberFormatter { buf.Append (full.GetName (type.BaseType).Substring ("class ".Length)); } bool first = true; - foreach (var name in type.Interfaces.Where (i => MDocUpdater.IsPublic (i.Resolve ())) - .Select (i => full.GetName (i)) + foreach (var name in type.Interfaces.Where (i => MDocUpdater.IsPublic (i.InterfaceType.Resolve ())) + .Select (i => full.GetName (i.InterfaceType)) .OrderBy (n => n)) { if (first) { buf.Append (" implements "); @@ -4904,7 +4959,7 @@ class ILFullMemberFormatter : MemberFormatter { .Append (val.ToString ()) .Append (')'); else if (val is IFormattable) { - string value = ((IFormattable)val).ToString(); + string value = ((IFormattable)val).ToString(null, CultureInfo.InvariantCulture); buf.Append (" = "); if (val is string) buf.Append ("\"" + value + "\""); @@ -5463,7 +5518,7 @@ class CSharpFullMemberFormatter : MemberFormatter { else if (val is Enum) buf.Append (" = ").Append (val.ToString ()); else if (val is IFormattable) { - string value = ((IFormattable)val).ToString(); + string value = ((IFormattable)val).ToString(null, CultureInfo.InvariantCulture); if (val is string) value = "\"" + value + "\""; buf.Append (" = ").Append (value); @@ -5615,15 +5670,6 @@ class SlashDocMemberFormatter : MemberFormatter { return buf; } - public override string GetDeclaration (MemberReference member) - { - TypeReference r = member as TypeReference; - if (r != null) { - return "T:" + GetTypeName (r); - } - return base.GetDeclaration (member); - } - protected override string GetConstructorName (MethodReference constructor) { return GetMethodDefinitionName (constructor, "#ctor");