InheritDocumentationComponent.cs :  » Development » Sandcastle » Microsoft » Ddue » Tools » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Development » Sandcastle 
Sandcastle » Microsoft » Ddue » Tools » InheritDocumentationComponent.cs
// ------------------------------------------------------------------------------------------------
// <copyright file="InheritDocumentationComponent.cs" company="Microsoft">
//      Copyright  Microsoft Corporation.
//      This source file is subject to the Microsoft Permissive License.
//      See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
//      All other rights reserved.
// </copyright>
// <summary>Contains code that indexes XML comments files for <inheritdoc /> tags, reflection files
// for API information and produces a new XML comments file containing the inherited documentation
// for use by Sandcastle.
// </summary>
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Ddue.Tools{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Xml;
    using System.Xml.XPath;
    using System.Configuration;
    using System.Globalization;
    using Microsoft.Ddue.Tools.CommandLine;
   
    /// <summary>
    /// InheritDocumentationComponent class.
    /// </summary>
    public class InheritDocumentationComponent : CopyComponent
    {
        #region private members
        /// <summary>
        /// XPathExpression for API name.
        /// </summary>
        private static XPathExpression apiNameExpression = XPathExpression.Compile("string(apidata/@name)");

        /// <summary>
        /// XPathExpression for API group.
        /// </summary>
        private static XPathExpression apiGroupExpression = XPathExpression.Compile("string(apidata/@group)");
        
        /// <summary>
        /// XPathExpression for API subgroup.
        /// </summary>
        private static XPathExpression apiSubgroupExpression = XPathExpression.Compile("string(apidata/@subgroup)");

        /// <summary>
        /// XPathExpression for API ancestors.
        /// </summary>
        private static XPathExpression typeExpression = XPathExpression.Compile("family/ancestors/type/@api");

        /// <summary>
        /// XPathExpression for API type interface implementations.
        /// </summary>
        private static XPathExpression interfaceImplementationExpression = XPathExpression.Compile("implements/type/@api");

        /// <summary>
        /// XPathExpression for API containers.
        /// </summary>
        private static XPathExpression containerTypeExpression = XPathExpression.Compile("string(containers/type/@api)");

        /// <summary>
        /// XPathExpression for override members.
        /// </summary>
        private static XPathExpression overrideMemberExpression = XPathExpression.Compile("overrides/member/@api");

        /// <summary>
        /// XPathExpression for API member interface implementaions.
        /// </summary>
        private static XPathExpression interfaceImplementationMemberExpression = XPathExpression.Compile("implements/member/@api");

        /// <summary>
        /// XPathExpression for <inheritdoc /> nodes.
        /// </summary>
        private static XPathExpression inheritDocExpression = XPathExpression.Compile("//inheritdoc");

        /// <summary>
        /// XPathExpression that looks for example, filterpriority, preliminary, remarks, returns, summary, threadsafety and value nodes.
        /// </summary>
        private static XPathExpression tagsExpression = XPathExpression.Compile("example|filterpriority|preliminary|remarks|returns|summary|threadsafety|value");

        /// <summary>
        /// XPathExpression for source nodes.
        /// </summary>
        private static XPathExpression sourceExpression;

        /// <summary>
        /// Document to be parsed.
        /// </summary>
        private XmlDocument sourceDocument;

        /// <summary>
        /// A cache for comment files.
        /// </summary>
        private IndexedDocumentCache index;

        /// <summary>
        /// A cache for reflection files.
        /// </summary>
        private IndexedDocumentCache reflectionIndex;
        #endregion

        #region constructor
        /// <summary>
        /// Creates an instance of InheritDocumentationComponent class.
        /// </summary>
        /// <param name="configuration">Configuration section to be parsed.</param>
        /// <param name="data">A dictionary object with string as key and object as value.</param>
        public InheritDocumentationComponent(XPathNavigator configuration, Dictionary<string, object> data)
            : base(configuration, data)
        {
            // get the copy commands
            XPathNodeIterator copy_nodes = configuration.Select("copy");
            foreach (XPathNavigator copy_node in copy_nodes)
            {
                // get the comments info
                string source_name = copy_node.GetAttribute("name", string.Empty);
            if (String.IsNullOrEmpty(source_name))
                {
                    throw new ConfigurationErrorsException("Each copy command must specify an index to copy from.");
                }

                // get the reflection info
                string reflection_name = copy_node.GetAttribute("use", String.Empty);
                if (String.IsNullOrEmpty(reflection_name))
                {
                    throw new ConfigurationErrorsException("Each copy command must specify an index to get reflection information from.");
                }
                               
                this.index = (IndexedDocumentCache)data[source_name];
                this.reflectionIndex = (IndexedDocumentCache)data[reflection_name];
             }
        }
        #endregion

        #region methods
        /// <summary>
        /// Deletes the specified node and logs the message.
        /// </summary>
        /// <param name="inheritDocNodeNavigator">navigator for inheritdoc node</param>
        /// <param name="key">Id of the topic specified</param>
        public static void DeleteNode(XPathNavigator inheritDocNodeNavigator, string key)
        {
            ConsoleApplication.WriteMessage(LogLevel.Info, string.Format(CultureInfo.InvariantCulture, "Comments are not found for topic:{0}", key));
            inheritDocNodeNavigator.DeleteSelf();
        }

        /// <summary>
        /// Implement inheritDocumentation.
        /// </summary>
        /// <param name="document">document to be parsed</param>
        /// <param name="key">Id pf the topic specified</param>
        public override void Apply(XmlDocument document, string key) 
        {
            // default selection filter set not to inherit <overloads>.
            sourceExpression = XPathExpression.Compile("*[not(local-name()='overloads')]");
            this.sourceDocument = document;
            this.InheritDocumentation(key);
        }

        /// <summary>
        /// Inherit the documentation.
        /// </summary>
        /// <param name="key">Id of the topic specified</param>
        public void InheritDocumentation(string key)
        {
            foreach (XPathNavigator inheritDocNodeNavigator in this.sourceDocument.CreateNavigator().Select(inheritDocExpression))
            {
                inheritDocNodeNavigator.MoveToParent();

                XPathNodeIterator iterator = (XPathNodeIterator) inheritDocNodeNavigator.CreateNavigator().Evaluate(tagsExpression);
                
                // do not inherit the comments if the tags specified in tagsExpression are already present.
                if (iterator.Count != 0) 
                {
                    inheritDocNodeNavigator.MoveTo(this.sourceDocument.CreateNavigator().SelectSingleNode(inheritDocExpression));
                    inheritDocNodeNavigator.DeleteSelf();
                    continue; 
                }
                     
                inheritDocNodeNavigator.MoveTo(this.sourceDocument.CreateNavigator().SelectSingleNode(inheritDocExpression));

                // Inherit from the specified API [id=cref].
                string cref = inheritDocNodeNavigator.GetAttribute("cref", string.Empty);

                if (!string.IsNullOrEmpty(cref))
                {
                    XPathNavigator contentNodeNavigator = this.index.GetContent(cref);

                    // if no comments were found for the specified api, delete the <inheritdoc /> node,
                    // otherwise update the <inheritdoc /> node with the comments from the specified api.
                    if (contentNodeNavigator == null)
                    {
                        DeleteNode(inheritDocNodeNavigator, cref);
                    }
                    else
                    {
                        this.UpdateNode(inheritDocNodeNavigator, contentNodeNavigator);
                        if (this.sourceDocument.CreateNavigator().Select(inheritDocExpression).Count != 0)
                        {
                            this.InheritDocumentation(cref);
                        }
                    }
                }
                else
                {
                    XPathNavigator reflectionNodeNavigator = this.reflectionIndex.GetContent(key);

                    // no reflection information was found for the api, so delete <inheritdoc /> node.
                    if (reflectionNodeNavigator == null)
                    {
                        DeleteNode(inheritDocNodeNavigator, key);
                        continue;
                    }

                    string group = (string)reflectionNodeNavigator.Evaluate(apiGroupExpression);
                    string subgroup = (string)reflectionNodeNavigator.Evaluate(apiSubgroupExpression);
                                     
                    if (group == "type")
                    {
                        // Inherit from base types
                        XPathNodeIterator typeNodeIterator = (XPathNodeIterator)reflectionNodeNavigator.Evaluate(typeExpression);
                        this.GetComments(typeNodeIterator, inheritDocNodeNavigator);

                        // no <inheritdoc /> nodes were found, so continue with next iteration. Otherwise inherit from interface implementation types.
                        if (this.sourceDocument.CreateNavigator().Select(inheritDocExpression).Count == 0)
                        {
                            continue;
                        }

                        // Inherit from interface implementation types
                        XPathNodeIterator interfaceNodeIterator = (XPathNodeIterator)reflectionNodeNavigator.Evaluate(interfaceImplementationExpression);
                        this.GetComments(interfaceNodeIterator, inheritDocNodeNavigator);
                    }
                    else if (group == "member")
                    {
                        // constructors do not have override member information in reflection files, so search all the base types for a matching signature.
                        if (subgroup == "constructor")
                        {
                            string name = (string)reflectionNodeNavigator.Evaluate(apiNameExpression);
                            string typeApi = (string) reflectionNodeNavigator.Evaluate(containerTypeExpression);

                            // no container type api was found, so delete <inheritdoc /> node.
                            if (string.IsNullOrEmpty(typeApi))
                            {
                                DeleteNode(inheritDocNodeNavigator, key);
                                continue;
                            }

                            reflectionNodeNavigator = this.reflectionIndex.GetContent(typeApi);
                            
                            // no reflection information for container type api was found, so delete <inheritdoc /> node.
                            if (reflectionNodeNavigator == null)
                            {
                                DeleteNode(inheritDocNodeNavigator, key);
                                continue;
                            }

                            XPathNodeIterator containerIterator = reflectionNodeNavigator.Select(typeExpression);
                                                    
                            foreach (XPathNavigator containerNavigator in containerIterator)
                            {
                                string constructorId = string.Format(CultureInfo.InvariantCulture, "M:{0}.{1}", containerNavigator.Value.Substring(2), name.Replace('.', '#'));
                                XPathNavigator contentNodeNavigator = this.index.GetContent(constructorId);

                                if (contentNodeNavigator == null)
                                {
                                    continue;
                                }

                                this.UpdateNode(inheritDocNodeNavigator, contentNodeNavigator);

                                if (this.sourceDocument.CreateNavigator().Select(inheritDocExpression).Count == 0)
                                {
                                    break;
                                }
                                else
                                {
                                    inheritDocNodeNavigator.MoveTo(this.sourceDocument.CreateNavigator().SelectSingleNode(inheritDocExpression));
                                }
                            }
                        }
                        else
                        {
                            // Inherit from override members.
                            XPathNodeIterator memberNodeIterator = (XPathNodeIterator)reflectionNodeNavigator.Evaluate(overrideMemberExpression);
                            this.GetComments(memberNodeIterator, inheritDocNodeNavigator);

                            if (this.sourceDocument.CreateNavigator().Select(inheritDocExpression).Count == 0)
                            {
                                continue;
                            }

                            // Inherit from interface implementations members.
                            XPathNodeIterator interfaceNodeIterator = (XPathNodeIterator)reflectionNodeNavigator.Evaluate(interfaceImplementationMemberExpression);
                            this.GetComments(interfaceNodeIterator, inheritDocNodeNavigator);
                        }
                    }

                    // no comments were found, so delete <iheritdoc /> node.
                    if (this.sourceDocument.CreateNavigator().Select(inheritDocExpression).Count != 0)
                    {
                        DeleteNode(inheritDocNodeNavigator, key);
                    }
                }
            }
        }

        /// <summary>
        /// Updates the node replacing inheritdoc node with comments found.
        /// </summary>
        /// <param name="inheritDocNodeNavigator">Navigator for inheritdoc node</param>
        /// <param name="contentNodeNavigator">Navigator for content</param>
        public void UpdateNode(XPathNavigator inheritDocNodeNavigator, XPathNavigator contentNodeNavigator)
        {
            // retrieve the selection filter if specified.
            string selectValue = inheritDocNodeNavigator.GetAttribute("select", string.Empty);
                        
            if (!string.IsNullOrEmpty(selectValue))
            {
                sourceExpression = XPathExpression.Compile(selectValue);
            }
            
            inheritDocNodeNavigator.MoveToParent();
                        
            if (inheritDocNodeNavigator.LocalName != "comments" && inheritDocNodeNavigator.LocalName != "element")
            {
                sourceExpression = XPathExpression.Compile(inheritDocNodeNavigator.LocalName);
            }
            else 
            {
                inheritDocNodeNavigator.MoveTo(this.sourceDocument.CreateNavigator().SelectSingleNode(inheritDocExpression)); 
            }
           
            XPathNodeIterator sources = (XPathNodeIterator) contentNodeNavigator.CreateNavigator().Evaluate(sourceExpression);
            inheritDocNodeNavigator.DeleteSelf();

            // append the source nodes to the target node
            foreach (XPathNavigator source in sources)
            {
               inheritDocNodeNavigator.AppendChild(source);
            }
        }

        /// <summary>
        /// Gets the comments for inheritdoc node.
        /// </summary>
        /// <param name="iterator">Iterator for API information</param>
        /// <param name="inheritDocNodeNavigator">Navigator for inheritdoc node</param>
        public void GetComments(XPathNodeIterator iterator, XPathNavigator inheritDocNodeNavigator)
        {
            foreach (XPathNavigator navigator in iterator)
            {
                XPathNavigator contentNodeNavigator = this.index.GetContent(navigator.Value);

                if (contentNodeNavigator == null)
                {
                    continue;
                }

                this.UpdateNode(inheritDocNodeNavigator, contentNodeNavigator);

                if (this.sourceDocument.CreateNavigator().Select(inheritDocExpression).Count == 0)
                {
                    break;
                }
                else
                {
                    inheritDocNodeNavigator.MoveTo(this.sourceDocument.CreateNavigator().SelectSingleNode(inheritDocExpression));
                }
            }
        }
        #endregion
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.