summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/BuildAssembler/CopyComponents
diff options
context:
space:
mode:
Diffstat (limited to 'tools/Sandcastle/Source/BuildAssembler/CopyComponents')
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj74
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj.vspscc10
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs370
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/CopyComponents/Properties/AssemblyInfo.cs41
4 files changed, 495 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj
new file mode 100644
index 0000000..4f26673
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj
@@ -0,0 +1,74 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{E64725D7-2208-4C28-922D-B6543C0BC483}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CopyComponents</RootNamespace>
+ <AssemblyName>CopyComponents</AssemblyName>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>
+ </AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="InheritDocumentationComponent.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\BuildComponents\BuildComponents.csproj">
+ <Project>{30773718-BC7C-4FCC-A9C2-7EE61DF4EC41}</Project>
+ <Name>BuildComponents</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\CommandLine\CommandLine.csproj">
+ <Project>{6CF7CA42-3706-4F6B-A2B4-10EF3F511888}</Project>
+ <Name>CommandLine</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- Copy the output assemblies to a common binaries directory (ProductionTools). -->
+ <Target Name="AfterBuild">
+ <CreateItem Include="$(OutputPath)\$(AssemblyName).*">
+ <Output TaskParameter="Include" ItemName="ProductionFiles" />
+ </CreateItem>
+ <Copy SourceFiles="@(ProductionFiles)" DestinationFolder="..\..\..\ProductionTools" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj.vspscc b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj.vspscc
new file mode 100644
index 0000000..b6d3289
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/CopyComponents.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs
new file mode 100644
index 0000000..9bb045d
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/InheritDocumentationComponent.cs
@@ -0,0 +1,370 @@
+// ------------------------------------------------------------------------------------------------
+// <copyright file="InheritDocumentationComponent.cs" company="Microsoft">
+// Copyright (c) Microsoft Corporation. All 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
+ }
+}
diff --git a/tools/Sandcastle/Source/BuildAssembler/CopyComponents/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3c269cf
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/CopyComponents/Properties/AssemblyInfo.cs
@@ -0,0 +1,41 @@
+//--------------------------------------------------------------------------
+// <copyright file="AssemblyInfo.cs" company="Microsoft">
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// </copyright>
+// <summary>Contains metadata information for the assembly.</summary>
+//--------------------------------------------------------------------------
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CopyComponents")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CopyComponents")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b14061be-8075-4418-a99f-432362137031")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("2.4.10522.00")]
+[assembly: AssemblyFileVersion("2.4.10522.00")]