-
Notifications
You must be signed in to change notification settings - Fork 3.8k
[mdoc] Platform/Owner tagging #1460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,7 +31,8 @@ public static void PopulateTreeFromIndexFile (string indexFilePath, | |
| IDocStorage storage, | ||
| Dictionary<string, XElement> nsSummaries, | ||
| Func<XElement, string> indexGenerator = null, | ||
| IEcmaProviderFileSource fileSource = null) | ||
| IEcmaProviderFileSource fileSource = null, | ||
| List<string> ownerList = null) | ||
| { | ||
| fileSource = fileSource ?? DefaultEcmaProviderFileSource.Default; | ||
| var root = tree.RootNode; | ||
|
|
@@ -45,115 +46,138 @@ public static void PopulateTreeFromIndexFile (string indexFilePath, | |
| indexGenerator = indexGenerator ?? (_ => resID++.ToString ()); | ||
|
|
||
| using (var reader = fileSource.GetIndexReader (indexFilePath)) { | ||
| reader.ReadToFollowing ("Types"); | ||
| var types = XElement.Load (reader.ReadSubtree ()); | ||
|
|
||
| foreach (var ns in types.Elements ("Namespace")) { | ||
| var nsName = (string)ns.Attribute ("Name"); | ||
| nsName = !string.IsNullOrEmpty (nsName) ? nsName : "global"; | ||
| var nsNode = root.GetOrCreateNode (nsName, "N:" + nsName); | ||
|
|
||
| XElement nsElements; | ||
| if (!nsSummaries.TryGetValue (nsName, out nsElements)) | ||
| nsSummaries[nsName] = nsElements = new XElement ("elements", | ||
| new XElement ("summary"), | ||
| new XElement ("remarks")); | ||
| //Add namespace summary and remarks data from file, if available | ||
| var nsFileName = fileSource.GetNamespaceXmlPath(asm, nsName); | ||
|
|
||
| if(File.Exists(nsFileName)){ | ||
| var nsEl = fileSource.GetNamespaceElement (nsFileName); | ||
|
|
||
| nsElements.Element ("summary").ReplaceWith (nsEl.Descendants ("summary").First ()); | ||
| nsElements.Element ("remarks").ReplaceWith (nsEl.Descendants ("remarks").First ()); | ||
| }else{ | ||
| Console.WriteLine ("Error reading namespace XML for {0} at {1}", nsName, nsFileName); | ||
| } | ||
|
|
||
| foreach (var type in ns.Elements ("Type")) { | ||
| // Add the XML file corresponding to the type to our storage | ||
| var id = indexGenerator (type); | ||
| string typeFilePath; | ||
| var typeDocument = EcmaDoc.LoadTypeDocument (asm, nsName, type.Attribute ("Name").Value, out typeFilePath, fileSource); | ||
| if (typeDocument == null) | ||
| continue; | ||
|
|
||
| // write the document (which may have been modified by the fileSource) to the storage | ||
| MemoryStream io = new MemoryStream (); | ||
| using (var writer = XmlWriter.Create (io)) { | ||
| typeDocument.WriteTo (writer); | ||
| reader.MoveToContent (); | ||
| while (reader.Read ()) { | ||
| if (reader.NodeType == XmlNodeType.Element) { | ||
| if (reader.Name == "Owner") { | ||
| try { | ||
| var owners = XElement.Load (reader.ReadSubtree ()); | ||
| foreach (var owner in owners.Elements ("Owner")) { | ||
| var ownerValue = owner.Value; | ||
| ownerList.Add (ownerValue); | ||
| } | ||
| } | ||
| catch (InvalidOperationException ex) { | ||
| Console.WriteLine ("Unable to read Owner element from {0}: {1}", indexFilePath, ex); | ||
| } | ||
| } | ||
| io.Seek (0, SeekOrigin.Begin); | ||
| storage.Store (id, io); | ||
|
|
||
| nsElements.Add (ExtractClassSummary (typeDocument)); | ||
|
|
||
| var typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type); | ||
| var url = idPrefix + id + '#' + typeCaption + '/'; | ||
| typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type, true); | ||
| var typeNode = nsNode.CreateNode (typeCaption, url); | ||
|
|
||
| // Add meta "Members" node | ||
| typeNode.CreateNode ("Members", "*"); | ||
| var membersNode = typeDocument.Root.Element ("Members"); | ||
| if (membersNode == null || !membersNode.Elements ().Any ()) | ||
| continue; | ||
| var members = membersNode | ||
| .Elements ("Member") | ||
| .ToLookup (EcmaDoc.GetMemberType); | ||
|
|
||
| foreach (var memberType in members) { | ||
| // We pluralize the member type to get the caption and take the first letter as URL | ||
| var node = typeNode.CreateNode (EcmaDoc.PluralizeMemberType (memberType.Key), memberType.Key[0].ToString ()); | ||
| var memberIndex = 0; | ||
|
|
||
| var isCtors = memberType.Key[0] == 'C'; | ||
|
|
||
| // We do not escape much member name here | ||
| foreach (var memberGroup in memberType.GroupBy (m => MakeMemberCaption (m, isCtors))) { | ||
| if (memberGroup.Count () > 1) { | ||
| // Generate overload | ||
| var overloadCaption = MakeMemberCaption (memberGroup.First (), false); | ||
| var overloadNode = node.CreateNode (overloadCaption, overloadCaption); | ||
| foreach (var member in memberGroup) | ||
| overloadNode.CreateNode (MakeMemberCaption (member, true), (memberIndex++).ToString ()); | ||
| overloadNode.Sort (); | ||
| } else { | ||
| // We treat constructor differently by showing their argument list in all cases | ||
| node.CreateNode (MakeMemberCaption (memberGroup.First (), isCtors), (memberIndex++).ToString ()); | ||
| else if (reader.Name == "Types") { | ||
|
|
||
| XElement types = XElement.Load (reader.ReadSubtree ()); | ||
|
|
||
| foreach (var ns in types.Elements ("Namespace")) { | ||
| var nsName = (string)ns.Attribute ("Name"); | ||
| var nsPath = (string)ns.Attribute ("Path"); | ||
| nsName = !string.IsNullOrEmpty (nsName) ? nsName : "global"; | ||
| nsPath = !string.IsNullOrEmpty (nsPath) ? nsPath : nsName; | ||
| var nsNode = root.GetOrCreateNode (nsName, "N:" + nsName); | ||
|
|
||
| XElement nsElements; | ||
| if (!nsSummaries.TryGetValue (nsName, out nsElements)) | ||
| nsSummaries[nsName] = nsElements = new XElement ("elements", | ||
| new XElement ("summary"), | ||
| new XElement ("remarks")); | ||
| //Add namespace summary and remarks data from file, if available | ||
| var nsFileName = fileSource.GetNamespaceXmlPath(asm, nsPath); | ||
|
|
||
| if(File.Exists(nsFileName)){ | ||
| var nsEl = fileSource.GetNamespaceElement (nsFileName); | ||
|
|
||
| nsElements.Element ("summary").ReplaceWith (nsEl.Descendants ("summary").First ()); | ||
| nsElements.Element ("remarks").ReplaceWith (nsEl.Descendants ("remarks").First ()); | ||
| }else{ | ||
| Console.WriteLine ("Error reading namespace XML for {0} at {1}", nsName, nsFileName); | ||
| } | ||
|
|
||
| foreach (var type in ns.Elements ("Type")) { | ||
| // Add the XML file corresponding to the type to our storage | ||
| var id = indexGenerator (type); | ||
|
|
||
| string typeFilePath; | ||
| var typeDocument = EcmaDoc.LoadTypeDocument (asm, nsName, nsPath, type.Attribute ("Name").Value, out typeFilePath, fileSource); | ||
| if (typeDocument == null) | ||
| continue; | ||
|
|
||
| // write the document (which may have been modified by the fileSource) to the storage | ||
| MemoryStream io = new MemoryStream (); | ||
| using (var writer = XmlWriter.Create (io)) { | ||
| typeDocument.WriteTo (writer); | ||
| } | ||
| io.Seek (0, SeekOrigin.Begin); | ||
| storage.Store (id, io); | ||
|
|
||
| nsElements.Add (ExtractClassSummary (typeDocument)); | ||
|
|
||
| var typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type); | ||
| var url = idPrefix + id + '#' + typeCaption + '/'; | ||
| typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type, true); | ||
| var typeNode = nsNode.CreateNode (typeCaption, url); | ||
|
|
||
| // Add meta "Members" node | ||
| typeNode.CreateNode ("Members", "*"); | ||
| var membersNode = typeDocument.Root.Element ("Members"); | ||
| if (membersNode == null || !membersNode.Elements ().Any ()) | ||
| continue; | ||
| var members = membersNode | ||
| .Elements ("Member") | ||
| .ToLookup (EcmaDoc.GetMemberType); | ||
|
|
||
| foreach (var memberType in members) { | ||
| // We pluralize the member type to get the caption and take the first letter as URL | ||
| var node = typeNode.CreateNode (EcmaDoc.PluralizeMemberType (memberType.Key), memberType.Key[0].ToString ()); | ||
| var memberIndex = 0; | ||
|
|
||
| var isCtors = memberType.Key[0] == 'C'; | ||
|
|
||
| // We do not escape much member name here | ||
| foreach (var memberGroup in memberType.GroupBy (m => MakeMemberCaption (m, isCtors))) { | ||
| if (memberGroup.Count () > 1) { | ||
| // Generate overload | ||
| var overloadCaption = MakeMemberCaption (memberGroup.First (), false); | ||
| var overloadNode = node.CreateNode (overloadCaption, overloadCaption); | ||
| foreach (var member in memberGroup) | ||
| overloadNode.CreateNode (MakeMemberCaption (member, true), (memberIndex++).ToString ()); | ||
| overloadNode.Sort (); | ||
| } else { | ||
| // We treat constructor differently by showing their argument list in all cases | ||
| node.CreateNode (MakeMemberCaption (memberGroup.First (), isCtors), (memberIndex++).ToString ()); | ||
| } | ||
| } | ||
| node.Sort (); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| nsNode.Sort (); | ||
| } | ||
| node.Sort (); | ||
| root.Sort (); | ||
| } | ||
| } | ||
|
|
||
| nsNode.Sort (); | ||
| } | ||
| root.Sort (); | ||
| } | ||
| } | ||
|
|
||
| // Utility methods | ||
|
|
||
| public static XDocument LoadTypeDocument (string basePath, string nsName, string typeName, IEcmaProviderFileSource fileSource = null) | ||
| public static XDocument LoadTypeDocument (string basePath, string nsName, string nsPath, string typeName, IEcmaProviderFileSource fileSource = null) | ||
| { | ||
| string dummy; | ||
| return LoadTypeDocument (basePath, nsName, typeName, out dummy, fileSource ?? DefaultEcmaProviderFileSource.Default); | ||
| return LoadTypeDocument (basePath, nsName, nsPath, typeName, out dummy, fileSource ?? DefaultEcmaProviderFileSource.Default); | ||
| } | ||
|
|
||
| public static XDocument LoadTypeDocument (string basePath, string nsName, string typeName, out string finalPath, IEcmaProviderFileSource fileSource = null) | ||
| public static XDocument LoadTypeDocument (string basePath, string nsName, string nsPath, string typeName, out string finalPath, IEcmaProviderFileSource fileSource = null) | ||
| { | ||
| fileSource = fileSource ?? DefaultEcmaProviderFileSource.Default; | ||
|
|
||
| finalPath = fileSource.GetTypeXmlPath (basePath, nsName, typeName); | ||
| finalPath = fileSource.GetTypeXmlPath (basePath, nsPath, typeName); | ||
| if (!File.Exists (finalPath)) { | ||
| Console.Error.WriteLine ("Warning: couldn't process type file `{0}' as it doesn't exist", finalPath); | ||
| return null; | ||
| } | ||
|
|
||
| XDocument doc = null; | ||
| try { | ||
| doc = fileSource.GetTypeDocument(finalPath); | ||
| doc = fileSource.GetTypeDocument (finalPath, nsName); | ||
| } catch (Exception e) { | ||
| Console.WriteLine ("Document `{0}' is unparsable, {1}", finalPath, e.ToString ()); | ||
| } | ||
|
|
@@ -578,16 +602,19 @@ internal static string MakeOperatorSignature (XElement member, out string member | |
|
|
||
| static XElement ExtractClassSummary (XDocument typeDoc) | ||
| { | ||
| string name = typeDoc.Root.Attribute("Name").Value; | ||
| string fullName = typeDoc.Root.Attribute("FullName").Value; | ||
| string assemblyName = typeDoc.Root.Element("AssemblyInfo") != null ? typeDoc.Root.Element("AssemblyInfo").Element("AssemblyName").Value : string.Empty; | ||
| var docs = typeDoc.Root.Element("Docs"); | ||
| var summary = docs.Element("summary") ?? new XElement("summary"); | ||
| var remarks = docs.Element("remarks") ?? new XElement("remarks"); | ||
| string name = typeDoc.Root.Attribute ("Name").Value; | ||
|
||
| string fullName = typeDoc.Root.Attribute ("FullName").Value; | ||
| string assemblyName = typeDoc.Root.Element ("AssemblyInfo") != null ? typeDoc.Root.Element("AssemblyInfo").Element("AssemblyName").Value : string.Empty; | ||
| string owners = typeDoc.Root.Attribute ("owner") != null ? typeDoc.Root.Attribute ("owner").Value : string.Empty; | ||
| var docs = typeDoc.Root.Element ("Docs"); | ||
| var summary = docs.Element ("summary") ?? new XElement ("summary"); | ||
| var remarks = docs.Element ("remarks") ?? new XElement ("remarks"); | ||
|
|
||
| return new XElement ("class", | ||
| new XAttribute ("name", name ?? string.Empty), | ||
| new XAttribute ("fullname", fullName ?? string.Empty), | ||
| new XAttribute ("assembly", assemblyName ?? string.Empty), | ||
| new XAttribute ("owner", owners), | ||
| summary, | ||
| remarks); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PopulateTreeFromIndexFile()taking 8 parameters is a code smell; this is probably a sign that some refactoring is needed, e.g. turning this method into a class and each method parameter into a class property.It's also odd that EcmaDoc has only static members but is not a static class.
Fortunately, the EcmaDoc type is internal, but still; this is crazy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, as with the mutable static state, this is also another thing that I hesitantly added to avoid a big refactor. The only reason I went forward with it is because the parameters I was adding were optional, and really only useful when being called specifically from mdoc ... so it wouldn't break any other clients that might be using this API.
But you're right that it's a code smell ... if any cause comes up again to modify this code, I will certainly refactor rather than continue adding to the parameter list.