Example #1
0
        /// <summary>
        /// This adds documentation model elements to a general node
        /// </summary>
        /// <param name="memberNode">The member node to update</param>
        private void UpdateGeneralApiNode(ApiMember memberNode)
        {
            var containers = memberNode.Node.Element("containers");
            var type       = containers?.Element("type");
            var topicData  = new XElement("topicdata",
                                          new XAttribute("group", ApiMemberGroup.Api.ToString().ToLowerInvariant()),
                                          (type != null && apiMembers[type.Attribute("api").Value].Subgroup == ApiMemberGroup.Enumeration) ?
                                          new XAttribute("notopic", String.Empty) : null);
            string implementedApiType = null;

            // For EII members, add the name of the type to which the implemented member belongs to keep them
            // distinct if the name appears in multiple explicitly implemented types.
            if (memberNode.IsExplicitlyImplemented)
            {
                implementedApiType = memberNode.ImplementedType;

                int pos = implementedApiType.LastIndexOf('.');

                if (pos != -1)
                {
                    topicData.Add(new XAttribute("eiiName", implementedApiType.Substring(pos + 1) + "." + memberNode.Name));
                }
                else
                {
                    topicData.Add(new XAttribute("eiiName", implementedApiType.Substring(2) + "." + memberNode.Name));
                }
            }

            memberNode.Node.AddFirst(topicData);

            if (containers != null)
            {
                foreach (var l in containers.Elements("library"))
                {
                    this.AddLibraryAssemblyData(l, true);
                }
            }

            var memberData = memberNode.Node.Element("memberdata");

            if (memberData == null || memberNode.Subgroup == ApiMemberGroup.Field)
            {
                return;
            }

            // Add an overload ID to the memberdata element if needed.
            var    typeNode   = apiMembers[type.Attribute("api").Value];
            string overloadId = DetermineOverloadId(typeNode, memberNode);

            if (typeNode.Node.Element("elements").Elements("element").Any(
                    el => el.Attribute("api").Value == overloadId))
            {
                memberData.Add(new XAttribute("overload", overloadId));
            }
        }
Example #2
0
        /// <summary>
        /// Update an element node
        /// </summary>
        /// <param name="typeNode">The type node</param>
        /// <param name="member">The member for which to update the element node</param>
        /// <returns>The node itself if it is an <c>element</c> element or the original <c>element</c> node
        /// from the containing type if not.</returns>
        private static XElement UpdateElementNode(ApiMember typeNode, ApiMember member)
        {
            // If the node is an element, return it
            if (member.Node.Name == "element")
            {
                return(member.Node);
            }

            // Otherwise, look up and return the original element node in the type's element list
            var el = typeNode.Node.Element("elements").Elements("element").FirstOrDefault(
                mel => mel.Attribute("api").Value == member.MemberId);

            return(el);
        }
        /// <summary>
        /// Add a table of contents entry for a member
        /// </summary>
        /// <param name="writer">The XML writer to which the output is written</param>
        /// <param name="member">The member for which to add TOC entry</param>
        /// <param name="declaringTypePrefix">The declaring type's prefix used to filter members</param>
        private void AddMember(XmlWriter writer, ApiMember member, string declaringTypePrefix)
        {
            writer.WriteStartElement("topic");
            writer.WriteAttributeString("id", member.MemberId);
            writer.WriteAttributeString("file", member.TopicFilename);

            // Add child elements if any (members for an overload for example).  Only include direct members of
            // the given type.  Ignore inherited members.  Sort by parameter count and then by the type name
            // of the first parameter.
            var childMembers = member.ChildElements.Select(id => apiMembers.ContainsKey(id) ? apiMembers[id] : null).Where(
                m => m != null && m.MemberIdWithoutPrefix.StartsWith(declaringTypePrefix, StringComparison.Ordinal)).OrderBy(
                m => m.ParameterCount).ThenBy(m => m.FirstParameterTypeName);

            foreach (var m in childMembers)
            {
                AddMember(writer, m, declaringTypePrefix);
            }

            writer.WriteEndElement();
        }
        /// <summary>
        /// Add a member list topic and its children
        /// </summary>
        /// <param name="writer">The XML writer to which the output is written</param>
        /// <param name="list">The member list topic to output</param>
        /// <param name="declaringTypePrefix">The declaring type's prefix used to filter members</param>
        private void AddMemberListTree(XmlWriter writer, ApiMember list, string declaringTypePrefix)
        {
            writer.WriteStartElement("topic");
            writer.WriteAttributeString("id", list.MemberId);
            writer.WriteAttributeString("file", list.TopicFilename);

            // Add the child elements of the list.  Only include direct members of the given type.  Ignore
            // inherited members.  Sort by name (explicit interface implementation name if present or
            // the member name if not.
            var childMembers = list.ChildElements.Select(id => apiMembers.ContainsKey(id) ? apiMembers[id] : null).Where(
                m => m != null && m.MemberIdWithoutPrefix.StartsWith(declaringTypePrefix, StringComparison.Ordinal)).OrderBy(
                m => m.TopicEiiName ?? m.Name);

            foreach (var m in childMembers)
            {
                AddMember(writer, m, declaringTypePrefix);
            }

            writer.WriteEndElement();
        }
Example #5
0
        /// <summary>
        /// This is used to determine the ID of an overloads member entry
        /// </summary>
        /// <param name="typeNode">The type node to use</param>
        /// <param name="member">The member to use</param>
        /// <returns>The ID for the overloads member entry</returns>
        private static string DetermineOverloadId(ApiMember typeNode, ApiMember member)
        {
            string overloadId;

            if (member.IsExplicitlyImplemented)
            {
                string memberId = member.MemberIdWithoutParameters.Substring(2);
                overloadId = typeNode.MemberIdWithoutPrefix + "." + memberId.Substring(memberId.LastIndexOf('.') + 1);

                int pos = overloadId.LastIndexOf("``", StringComparison.Ordinal);

                if (pos != -1)
                {
                    overloadId = overloadId.Substring(0, pos);
                }
            }
            else
            {
                overloadId = typeNode.MemberIdWithoutPrefix;

                if (member.Subgroup == ApiMemberGroup.Constructor)
                {
                    overloadId += ".#ctor";
                }
                else
                {
                    if (member.SubSubgroup == ApiMemberGroup.Operator)
                    {
                        overloadId += ".op_" + member.Name;
                    }
                    else
                    {
                        overloadId += "." + member.Name;
                    }
                }
            }

            return("Overload:" + overloadId);
        }
        /// <summary>
        /// Add member list topics for a type (constructors, properties, methods, events, etc.).  The members are
        /// added as children of each list topic.
        /// </summary>
        /// <param name="writer">The XML writer to which the output is written</param>
        /// <param name="apiType">The type member for which to add member list topics</param>
        private void AddMemberListTopics(XmlWriter writer, ApiMember apiType)
        {
            string declaringTypePrefix = apiType.MemberIdWithoutPrefix + ".";

            // Only include direct members of the given type.  Ignore inherited members.
            var constructors = apiType.ChildElements.Select(id => apiMembers.ContainsKey(id) ? apiMembers[id] : null).Where(
                m => m != null && m.MemberIdWithoutPrefix.StartsWith(declaringTypePrefix, StringComparison.Ordinal) &&
                m.Subgroup == ApiMemberGroup.Constructor);

            // Constructors don't have a containing list topic so we need to get them separately
            foreach (var m in constructors)
            {
                AddMember(writer, m, declaringTypePrefix);
            }

            // Add lists for properties, methods, events, etc.  Some categories may not appear for a type.
            foreach (ApiMemberGroup listType in this.ListTopicOrder)
            {
                if (apiMembers.TryGetValue(listType.ToString() + "." + apiType.MemberId, out ApiMember list))
                {
                    AddMemberListTree(writer, list, declaringTypePrefix);
                }
            }
        }
Example #7
0
        /// <inheritdoc />
        public void ApplyDocumentModel(string reflectionDataFile, string docModelReflectionDataFile)
        {
            // Load the information needed to apply the document model
            using (XmlReader reader = XmlReader.Create(reflectionDataFile, new XmlReaderSettings {
                IgnoreWhitespace = true
            }))
            {
                reader.Read();

                while (!reader.EOF)
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.EndElement:
                        reader.Read();
                        break;

                    case XmlNodeType.Element:
                        switch (reader.Name)
                        {
                        case "api":
                            var node      = (XElement)XNode.ReadFrom(reader);
                            var apiMember = new ApiMember(node)
                            {
                                Node = node
                            };

                            apiMembers[apiMember.MemberId] = apiMember;
                            break;

                        case "assembly":
                            var assembly = new ApiAssemblyProperties((XElement)XNode.ReadFrom(reader));

                            assemblies[assembly.AssemblyName] = assembly;
                            break;

                        default:
                            reader.Read();
                            break;
                        }
                        break;

                    default:
                        reader.Read();
                        break;
                    }
                }
            }

            // Clone the file and add the document model elements
            using (XmlReader reader = XmlReader.Create(reflectionDataFile, new XmlReaderSettings {
                IgnoreWhitespace = true
            }))
                using (XmlWriter writer = XmlWriter.Create(docModelReflectionDataFile, new XmlWriterSettings {
                    Indent = true
                }))
                {
                    writer.WriteStartDocument();
                    reader.Read();

                    while (!reader.EOF)
                    {
                        switch (reader.NodeType)
                        {
                        case XmlNodeType.XmlDeclaration:
                        case XmlNodeType.EndElement:
                            if (reader.Name == "apis" && !String.IsNullOrWhiteSpace(this.RootNamespaceContainerId))
                            {
                                this.AddRootNamespaceContainer(writer);
                            }

                            reader.Read();
                            break;

                        case XmlNodeType.Element:
                            switch (reader.Name)
                            {
                            case "apis":
                            case "reflection":
                                writer.WriteStartElement(reader.Name);
                                reader.Read();
                                break;

                            case "api":
                                string id = reader.GetAttribute("id");

                                // Discard the file copy and use the one we loaded above
                                reader.ReadToNextSibling("api");

                                var apiMember = apiMembers[id];

                                if (apiMember.Group == ApiMemberGroup.Type)
                                {
                                    this.UpdateTypeApiNode(apiMember);
                                }
                                else
                                {
                                    this.UpdateGeneralApiNode(apiMember);
                                }

                                apiMember.Node.WriteTo(writer);

                                if (apiMember.Group == ApiMemberGroup.Type &&
                                    apiMember.Subgroup != ApiMemberGroup.Enumeration &&
                                    apiMember.Node.Element("elements") != null)
                                {
                                    this.AddMemberListApiElement(writer, ApiMemberGroup.Methods, apiMember);
                                    this.AddMemberListApiElement(writer, ApiMemberGroup.Operators, apiMember);
                                    this.AddMemberListApiElement(writer, ApiMemberGroup.Properties, apiMember);
                                    this.AddMemberListApiElement(writer, ApiMemberGroup.Events, apiMember);
                                    this.AddMemberListApiElement(writer, ApiMemberGroup.Fields, apiMember);
                                    this.AddMemberListApiElement(writer, ApiMemberGroup.AttachedProperties, apiMember);
                                    this.AddMemberListApiElement(writer, ApiMemberGroup.AttachedEvents, apiMember);
                                    this.AddOverloadListApiElements(writer, apiMember);
                                }
                                break;

                            default:
                                writer.WriteNode(reader.ReadSubtree(), true);
                                break;
                            }
                            break;

                        default:
                            reader.Read();
                            break;
                        }
                    }

                    writer.WriteEndDocument();
                }
        }
Example #8
0
        /// <summary>
        /// Update the member list elements with overload set entries
        /// </summary>
        /// <returns>An enumerable list of <c>element</c> elements for the member list</returns>
        private static IEnumerable <XElement> UpdateMemberListElements(ApiMember typeNode, IEnumerable <ApiMember> memberList)
        {
            string declaredPrefix = typeNode.MemberIdWithoutPrefix + ".";

            // Group EII members separately from non-EII members.  Extension methods are also separated.
            List <ApiMember> eiiMembers = new List <ApiMember>(), nonEiiMembers = new List <ApiMember>(),
                             extensionMethods = new List <ApiMember>();

            foreach (var m in memberList)
            {
                if (m.IsExplicitlyImplemented)
                {
                    eiiMembers.Add(m);
                }
                else
                {
                    if (m.SubSubgroup == ApiMemberGroup.Extension)
                    {
                        extensionMethods.Add(m);
                    }
                    else
                    {
                        nonEiiMembers.Add(m);
                    }
                }
            }

            // Extension methods are never grouped even when overloaded.  We just mark them with an attribute.
            var groupedMembers = eiiMembers.GroupBy(m => m.ImplementedType + "/" + m.Name + "/" +
                                                    m.Subgroup.ToString() + "/" + m.SubSubgroup).Concat(
                nonEiiMembers.GroupBy(m => m.Name + "/" + m.Subgroup.ToString() + "/" + m.SubSubgroup)).Concat(
                extensionMethods.GroupBy(m => m.Name)).OrderBy(
                m => m.First().SubSubgroup == ApiMemberGroup.Extension ? 0 : 1).ThenBy(
                m => m.First().MemberId).ToList();

            foreach (var g in groupedMembers)
            {
                var firstMember = g.First();

                if (g.Count() == 1)
                {
                    yield return(UpdateElementNode(typeNode, firstMember));
                }
                else
                {
                    // Extension methods just get an attribute
                    if (firstMember.SubSubgroup == ApiMemberGroup.Extension)
                    {
                        foreach (var m in g.OrderBy(m => m.ParameterCount).ThenBy(m => m.FirstParameterTypeName))
                        {
                            var elementNode = UpdateElementNode(typeNode, m);

                            elementNode.Add(new XAttribute("overload", "true"));

                            yield return(elementNode);
                        }
                    }
                    else
                    {
                        var overloadElement = new XElement("element");

                        overloadElement.Add(new XAttribute("api", DetermineOverloadId(typeNode, firstMember)));

                        foreach (var m in g.OrderBy(m => m.ParameterCount).ThenBy(m => m.FirstParameterTypeName).ThenBy(
                                     m => m.MemberIdWithoutPrefix))
                        {
                            overloadElement.Add(UpdateElementNode(typeNode, m));
                        }

                        yield return(overloadElement);
                    }
                }
            }
        }
Example #9
0
        /// <summary>
        /// Add overload list topics for each overloaded member in the type
        /// </summary>
        /// <param name="writer">The XML writer to which the element is added</param>
        /// <param name="typeNode">The type node to update</param>
        private void AddOverloadListApiElements(XmlWriter writer, ApiMember typeNode)
        {
            XElement containers = null;
            var      memberList = new List <ApiMember>();

            // Get members matching the subgroup or sub-subgroup
            foreach (var element in typeNode.Node.Element("elements").Elements("element"))
            {
                // Members with an apidata element are extension methods
                if (element.Attribute("api").Value.StartsWith("Overload:", StringComparison.Ordinal))
                {
                    var ol = new ApiMember(element)
                    {
                        Node = element
                    };

                    // Only generate an overload topic if there is at least one member in the containing type.
                    // If all overloads are inherited, ignore it.
                    var firstDeclaredMember = ol.Node.Elements("element").FirstOrDefault(
                        el => el.Attribute("api").Value.Substring(2).StartsWith(
                            typeNode.MemberIdWithoutPrefix + ".", StringComparison.Ordinal));

                    if (firstDeclaredMember != null)
                    {
                        // Use the container from the first declared member for the overloads topic
                        if (containers == null)
                        {
                            var fm = apiMembers[firstDeclaredMember.Attribute("api").Value];
                            containers = new XElement(fm.Node.Element("containers"));

                            foreach (var l in containers.Elements("library"))
                            {
                                this.AddLibraryAssemblyData(l, false);
                            }
                        }

                        memberList.Add(ol);
                    }
                }
            }

            if (memberList.Count == 0)
            {
                return;
            }

            // Create the member list node and add it to the file
            foreach (var m in memberList.OrderBy(m => m.MemberId))
            {
                var firstEl = m.Node.Element("element");

                if (!apiMembers.TryGetValue(firstEl.Attribute("api").Value, out ApiMember firstMember))
                {
                    firstMember = new ApiMember(firstEl)
                    {
                        Node = firstEl
                    }
                }
                ;

                var apidata = firstMember.Node.Element("apidata");

                var apiList = new XElement("api",
                                           new XAttribute("id", m.MemberId),
                                           new XElement("topicdata",
                                                        new XAttribute("name", firstMember.Name),
                                                        new XAttribute("group", ApiMemberGroup.List.ToString().ToLowerInvariant()),
                                                        new XAttribute("subgroup", ApiMemberGroup.Overload.ToString().ToLowerInvariant()),
                                                        new XAttribute("memberSubgroup", firstMember.Subgroup.ToString().ToLowerInvariant()),
                                                        new XAttribute("pseudo", "true")),
                                           apidata,
                                           new XElement("elements",
                                                        m.Node.Elements("element").Select(el => new XElement(el))),
                                           containers);

                apiList.WriteTo(writer);
            }
        }
Example #10
0
        /// <summary>
        /// Add a member list topic of the specified type for the given type node
        /// </summary>
        /// <param name="writer">The XML writer to which the element is added</param>
        /// <param name="listType">The list type to add</param>
        /// <param name="typeNode">The type node to update</param>
        private void AddMemberListApiElement(XmlWriter writer, ApiMemberGroup listType, ApiMember typeNode)
        {
            ApiMemberGroup subgroup = ApiMemberGroup.None, subsubgroup = ApiMemberGroup.None;

            switch (listType)
            {
            case ApiMemberGroup.Methods:
                subgroup = ApiMemberGroup.Method;
                break;

            case ApiMemberGroup.Operators:
                subsubgroup = ApiMemberGroup.Operator;
                break;

            case ApiMemberGroup.Properties:
                subgroup = ApiMemberGroup.Property;
                break;

            case ApiMemberGroup.Events:
                subgroup = ApiMemberGroup.Event;
                break;

            case ApiMemberGroup.Fields:
                subgroup = ApiMemberGroup.Field;
                break;

            case ApiMemberGroup.AttachedProperties:
                subsubgroup = ApiMemberGroup.AttachedProperty;
                break;

            case ApiMemberGroup.AttachedEvents:
                subsubgroup = ApiMemberGroup.AttachedEvent;
                break;

            default:
                throw new InvalidOperationException("Unexpected list type encountered");
            }

            var       memberList = new List <ApiMember>();
            ApiMember listElement, compareElement;

            // Get members matching the subgroup or sub-subgroup
            foreach (var element in typeNode.Node.Element("elements").Elements("element"))
            {
                // For overloads, use the first element so that we get the proper subgroup for comparison
                if (element.Attribute("api").Value.StartsWith("Overload:", StringComparison.Ordinal))
                {
                    listElement = new ApiMember(element)
                    {
                        Node = element
                    };
                    var firstEl = element.Element("element");

                    if (!apiMembers.TryGetValue(firstEl.Attribute("api").Value, out compareElement))
                    {
                        compareElement = new ApiMember(firstEl)
                        {
                            Node = firstEl
                        };
                    }
                }
                else
                {
                    // Members with an apidata element are extension methods
                    if (element.Element("apidata") == null)
                    {
                        listElement = compareElement = apiMembers[element.Attribute("api").Value];
                    }
                    else
                    {
                        listElement = compareElement = new ApiMember(element)
                        {
                            Node = element
                        }
                    };
                }

                if (subgroup == ApiMemberGroup.Method)
                {
                    // For methods we want everything but operators
                    if (compareElement.Subgroup == subgroup && compareElement.SubSubgroup != ApiMemberGroup.Operator)
                    {
                        memberList.Add(listElement);
                    }
                }
                else
                {
                    if ((subgroup == ApiMemberGroup.None && compareElement.SubSubgroup == subsubgroup) ||
                        (subgroup == compareElement.Subgroup && subsubgroup == compareElement.SubSubgroup))
                    {
                        memberList.Add(listElement);
                    }
                }
            }

            if (memberList.Count == 0)
            {
                return;
            }

            XElement apidata = typeNode.Node.Element("apidata"), typedata = typeNode.Node.Element("typedata"),
                     templates = typeNode.Node.Element("templates"), containers = new XElement(typeNode.Node.Element("containers"));

            // Add or update the type element.  A type element will already exist for nested types.  In such
            // cases, we just replace it for the list topic.
            var t = containers.Element("type");

            if (t != null)
            {
                t.RemoveAll();
                t.Add(new XAttribute("api", typeNode.MemberId));
            }
            else
            {
                containers.Add(new XElement("type", new XAttribute("api", typeNode.MemberId)));
            }

            // Create the member list node and add it to the file
            var apiList = new XElement("api",
                                       new XAttribute("id", listType.ToString() + "." + typeNode.MemberId),
                                       new XElement("topicdata",
                                                    new XAttribute("name", typeNode.Name),
                                                    new XAttribute("group", ApiMemberGroup.List.ToString().ToLowerInvariant()),
                                                    new XAttribute("subgroup", listType),
                                                    (subsubgroup != ApiMemberGroup.None) ? new XAttribute("subsubgroup", listType) : null,
                                                    new XAttribute("typeTopicId", typeNode.MemberId)),
                                       apidata, typedata, templates,
                                       new XElement("elements",
                                                    memberList.Select(m => UpdateElementNode(typeNode, m))),
                                       containers);

            apiList.WriteTo(writer);
        }
Example #11
0
        /// <summary>
        /// This adds documentation model elements to a type node
        /// </summary>
        /// <param name="typeNode">The type node to update</param>
        private void UpdateTypeApiNode(ApiMember typeNode)
        {
            typeNode.Node.AddFirst(new XElement("topicdata",
                                                new XAttribute("group", ApiMemberGroup.Api.ToString().ToLowerInvariant())));

            var containers = typeNode.Node.Element("containers");

            if (containers != null)
            {
                foreach (var l in containers.Elements("library"))
                {
                    this.AddLibraryAssemblyData(l, false);
                }
            }

            if (typeNode.Subgroup != ApiMemberGroup.Enumeration && typeNode.Node.Element("elements") != null)
            {
                var memberList = new List <ApiMember>();
                var elements   = typeNode.Node.Element("elements");

                foreach (var element in elements.Elements("element"))
                {
                    // Members with an apidata element are extension methods
                    if (element.Element("apidata") == null)
                    {
                        // Odd case: Sometimes a member makes it to the element list but doesn't appear in the
                        // file as an entry.  These will be omitted.
                        if (apiMembers.TryGetValue(element.Attribute("api").Value, out ApiMember m))
                        {
                            memberList.Add(m);
                        }

                        /*
                         * // TODO: Should probably look into this but.  Only happens on a couple of designer
                         * // classes in the .NET Framework so ignoring for now.
                         * else
                         *  System.Diagnostics.Debug.WriteLine("No API entry for " + element.Attribute("api").Value);
                         */
                    }
                    else
                    {
                        memberList.Add(new ApiMember(element)
                        {
                            Node = element
                        });
                    }
                }

                // Update the element list with overloads topics
                var newElementList = new List <XElement>();

                foreach (var el in UpdateMemberListElements(typeNode, memberList))
                {
                    newElementList.Add(el);
                }

                elements.RemoveAll();

                foreach (var el in newElementList)
                {
                    elements.Add(el);
                }
            }
        }
Example #12
0
 public static MethodEntryPoint entry(ApiMember src)
 => new MethodEntryPoint(src.Token, src.BaseAddress);
        /// <inheritdoc />
        public void GenerateApiTocFile(string reflectionDataFile, string tocFile)
        {
            ApiMember root = null, rootGroup = null;
            var       namespaces = new List <ApiMember>();

            // Load the API member information to determine how the TOC should be generated
            using (XmlReader reader = XmlReader.Create(reflectionDataFile, new XmlReaderSettings {
                IgnoreWhitespace = true
            }))
            {
                reader.Read();

                while (!reader.EOF)
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.EndElement:
                        reader.Read();
                        break;

                    case XmlNodeType.Element:
                        switch (reader.Name)
                        {
                        case "api":
                            var apiMember = new ApiMember((XElement)XNode.ReadFrom(reader));
#if DEBUG
                            if (apiMember.Group == ApiMemberGroup.Unknown || apiMember.Subgroup == ApiMemberGroup.Unknown ||
                                apiMember.TopicGroup == ApiMemberGroup.Unknown || apiMember.TopicSubgroup == ApiMemberGroup.Unknown)
                            {
                                throw new InvalidOperationException("Unknown group value: " + apiMember.MemberId +
                                                                    $" - API Data: {apiMember.Group}/{apiMember.Subgroup} Topic Data: {apiMember.TopicGroup} {apiMember.TopicSubgroup}");
                            }
#endif
                            if (apiMember.TopicGroup == ApiMemberGroup.Root)
                            {
                                if (root != null)
                                {
                                    throw new InvalidOperationException("Unexpected duplicate root container entry");
                                }

                                root = apiMember;
                            }
                            else
                            {
                                if (apiMember.TopicGroup == ApiMemberGroup.RootGroup)
                                {
                                    if (rootGroup != null)
                                    {
                                        throw new InvalidOperationException("Unexpected duplicate root group container entry");
                                    }

                                    rootGroup = apiMember;
                                }
                                else
                                {
                                    if (apiMember.Group == ApiMemberGroup.Namespace)
                                    {
                                        namespaces.Add(apiMember);
                                    }
                                }
                            }

                            apiMembers[apiMember.MemberId] = apiMember;
                            break;

                        default:
                            reader.Read();
                            break;
                        }
                        break;

                    default:
                        reader.Read();
                        break;
                    }
                }
            }

            // Generate the TOC
            using (XmlWriter writer = XmlWriter.Create(tocFile, new XmlWriterSettings {
                Indent = true
            }))
            {
                writer.WriteStartDocument();
                writer.WriteStartElement("topics");

                if (root != null)
                {
                    // "R:" root namespace container.  Create a root entry and an entry for each namespace and
                    // namespace group and their children.
                    writer.WriteStartElement("topic");
                    writer.WriteAttributeString("id", root.MemberId);
                    writer.WriteAttributeString("file", root.TopicFilename);

                    foreach (string child in root.ChildElements)
                    {
                        AddNamespaceOrTypeTopic(writer, child);
                    }

                    writer.WriteEndElement();
                }
                else if (rootGroup != null)
                {
                    // No root namespace container but has a "G:" root group.  There is no topic generated for
                    // the root group node, just its children.
                    foreach (string child in rootGroup.ChildElements)
                    {
                        AddNamespaceOrTypeTopic(writer, child);
                    }
                }
                else
                {
                    // No root namespace container and no grouped namespaces.  List the namespaces at the root
                    // level, each containing their children.
                    foreach (var ns in namespaces.OrderBy(n => n.MemberIdWithoutPrefix))
                    {
                        AddNamespaceOrTypeTopic(writer, ns.MemberId);
                    }
                }

                writer.WriteEndDocument();
            }
        }
Example #14
0
 public static MemoryAddress jit(ApiMember src)
 {
     sys.prepare(src.Method.MethodHandle);
     return(fptr(src.Method));
 }